{"_id":"ipfs-grpc-server","_rev":"239-57678f7064c2dc6650b35762c4f10f07","name":"ipfs-grpc-server","dist-tags":{"latest":"0.12.1","next":"0.12.0-7b79c1b8"},"versions":{"0.0.0":{"name":"ipfs-grpc-server","version":"0.0.0","description":"","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"author":"","license":"ISC","_id":"ipfs-grpc-server@0.0.0","_nodeVersion":"12.16.1","_npmVersion":"6.14.1","dist":{"integrity":"sha512-zCZpcW9AqULBkHTeKuqmmZUUUT/rJF8pmABYNn+4gZVW3ArISZAchJj4wvMUZFRjSf2zS2ilvV3V3LhvE9MdXg==","shasum":"b9cbd0dee3d640efc247da1b45ae013037d526a0","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.0.0.tgz","fileCount":1,"unpackedSize":212,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfn+61CRA9TVsSAnZWagAAx3oQAKTKkFgGOvD9e+ZNAJs3\nT7QNaeQ7e+s5PuUqxA2dF6TNlQrXR96KVDFCQvu5M7hUNbSNzJkgxSBZy2KC\n4r0cg7DNirxrSZc0RQWZVOPCFhcrfg0jRXvV5XZLBG5w8oeJjNcKKYy8kkN+\nNVUxkwLOevZt0kLqJs5FriUZk3x7J9G8nrrowMZ/dnLn7BQwKNYCFbHPQy/B\nqeOwK/vyqOQuv3E3NQdNRtPQW56PQ/d5GXamSiMbMlJ6qmZ+urwZ5m2qLI+y\n1x4lCVqRMcgPUkrpYae3jFHqbqgTagcUgEyultT7Hy+xpIiiY6Jm1uQBd0IB\nN5u6F0E/iNODjC28jDB1toAt8FL1NDun/FfdEaQpZz7TaqMnWNqyALMuTfw/\n+zjvn+tktsQC2PMCAZ2LwTgReoWtd78u8Rfiicncpi+Dwh41pGmdY/hactDY\nB6qRGdgYZawlBR7YrlBWoDt2f9+W3S8nj85iM1pdwJLW/xyo+0tLQNamXk1v\nwWs2/PyWW8pBWEykpm/V8VeOJGWcwKIb/mHDDfZP4NWsUm+WcaVaW0lTQb+8\n0o9o0Z3bWmlxGJqfJMCWUfkpkrQxj62mEF0uENOCShmt0EAiF02WTJElTmZw\nfSnL5frhz12rB8Xdhuf7bYlbreCA8Z6YKayzeyPyw7rUe/BsPTVobW7nZ8Ak\n9GhI\r\n=wNHS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCiVGw5JnIC+lGksR4/yL653Hus+qHwfKEoe0fNv4xouAIgY2mxaUtVYLxE5T4Ai49ELXRa2VVo6Z5vGZ8duPGZYtI="}]},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"}],"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.0.0_1604316852785_0.9104348200546681"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.0.1-rc.5957":{"name":"ipfs-grpc-server","version":"0.0.1-rc.5957","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","build":"npm run build:types","build:types":"tsc --build","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i typescript -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.0.1-rc.5957+ae497111","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^29.2.2","ipfs-core":"^0.2.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","typescript":"4.0.x","uint8arrays":"^1.1.0"},"gitHead":"ae4971113534c8f988aa14314e43a00fc3df854b","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.0.1-rc.5957","_nodeVersion":"14.15.3","_npmVersion":"lerna/3.22.1/node@v14.15.3+x64 (linux)","dist":{"integrity":"sha512-pdO6AT9/yOwre8piRNE1S+tYQU2FzJH/QUzmAl0L0vG6OfdEe4oMUkZixBBiXo3pUyBr1mPufVsHHbe7qTYiwQ==","shasum":"b03a247174181dfcd1bc9cdf73055ae17c169f60","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.0.1-rc.5957.tgz","fileCount":30,"unpackedSize":129608,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf3OsMCRA9TVsSAnZWagAA3f8QAI8Gr2yCGJ8C2plcq9ya\nAmWb7No4IK9ZdikR8pXLu9s4KplEXwcu1uEn7n7LuzBxWl+T4WQrYiUIDfJZ\n48XMR2fmdo5a+xyIIvwUOIyYAZWFxOzNXybOSAqqvea7t4HT7SX5jzbyG92h\nx06E86Y6FFlPpJG7mvON90Hah3wvi4i5KggwMIM3CVWzoG19V6UoKY7Geaso\nmYuDOTJBfII920+NO/FotuLGqDe1pqNfaN0eGmbCdREidccLgHuNtkVEstku\n9n0G3W67Z7vEnH9qEeOpVUJEDnawrJVKXMNXbWkEQyauSamrfYOBQHq7CuXa\n+s2YXnfKwG4cY+DdXXv9gg7jTSo+HRvfu8kXwTsg/vEyTVqKn4JjN1M+nbOn\nvIA9zUJlKLFNyeha2NAVIHmWna6GS0UD+4oDz+cKRs2CLWKJpJiMODTc3f2G\nNMHqaS7oZiIudpLIv40WtQ1xe9nQ4RwzdK7FQe1t8bdR6RmBug+t7hHFv+VJ\nSnqGzhNZLdv6E2IKoFhGKhgixjREQwMkQJbyvlo0/u4h3t3ubbCa0xiKeaZm\n+xpf2UPjwlDwKToJj8wfw/PMVNizQi59c7W9hkwrooVRijGtvQbkGMisT/xi\nUcJflDJKT6okHpY3IX1rQOx8vGEXwvXuSc+4atg/F4S+xNSwFx0RPuhDPRle\nAUan\r\n=1rCx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC7GkUtbxox67b8uoQ249EVBod4Epsk/MugEM8r2mS8LAIhAPS0nifApHA/qgjtkF+TIelpLl8K4RM0HGsGmVT3AhkX"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.0.1-rc.5957_1608313612494_0.9968255896808509"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.0.1-rc.5958":{"name":"ipfs-grpc-server","version":"0.0.1-rc.5958","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","build":"npm run build:types","build:types":"tsc --build","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i typescript -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.0.1-rc.5958+fad9b740","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^29.2.2","ipfs-core":"^0.2.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","typescript":"4.0.x","uint8arrays":"^1.1.0"},"gitHead":"fad9b7402e67a459e9967a1319870da165ba722a","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.0.1-rc.5958","_nodeVersion":"14.15.4","_npmVersion":"lerna/3.22.1/node@v14.15.4+x64 (linux)","dist":{"integrity":"sha512-EycuHougtJ01Qu8Dqj8LHirfoZRKbD1bYTdwNeM+JFFz0EYU1ii3t8yFaFPQw9BzPvgiuoaNbYYe/9Mc+Dwdgw==","shasum":"81faaf05c53578326e4fcbef4c0b64f188d8d8e2","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.0.1-rc.5958.tgz","fileCount":30,"unpackedSize":129608,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf/ubjCRA9TVsSAnZWagAAY1UP/RUIhZ3TOUOWFsvUS3vg\nc4A2TxH+EyeaWzCw4VP3+ddonv/bUw1B1ziCvSrtc4vivfFM5Dz96s/LWncA\nFZ4qNBZkGyzcpi5cjJX+JmUttAfHMidyICt48k0oAUdrgKvLRGUTOw3dGcxl\nyQ3dO5HUtZPfwXnyV1/j/y1jsaYgwqm8XavqJ92aXfxt9kC27KR6rKxmu8xu\n1ZziDK/VWQvX4CcB+n5Rh5+Z6Yx7hTKbdS0NMj0TW/61gOY65K7warPR52P0\nwEdpYZm9RGo5GMXQuC+hy3D7fbWclYd0DHodl2U5tLiMAH/dbICjFjT5t0il\nNtpMdztXm5HmFW3PdUHTdIyBYNNhmN/NtelGb0j4Yt6su0tp5lvBoXFSQurT\n54+5P349l9y7o6QJaBqUe5Ly7sUNVrmiCSj0XMXRB+ztIAOv0EXwDLHUJgwT\nF2k/y9cGbyx1rKRCziMNMizDExnhw+nCn+a0bYpYhnS1T7wzl42sZOCemOxy\ncwQw4abjkoAKfJeoCvDBUpkEETWuneEHbUI/hUa3s9b2Ouq7HvDyZGkueUwO\nt1UdEfN3BIYTxLppnG+YiDZbE/5hLAZhWJ8lTh3iNxmmXRWbqcK/3R5ybNFB\nMt6vmOYcymAa6hM8U1RuAmIml+nXZjcqScF9CHxCJbB+Q6ZAeFp6R5ge+KU3\nz9EP\r\n=Kxjp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDL1vqs3/uFgE/hfSf9XpsJoWFRKAIXfBLHf9TW7Jz+0AiAtWXD5g6zNI3ix3LKAW+buFcSK0E4aRJo8ivIfJAiO/w=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.0.1-rc.5958_1610540771287_0.6028104200999937"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.0.1-rc.5959":{"name":"ipfs-grpc-server","version":"0.0.1-rc.5959","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","build":"npm run build:types","build:types":"tsc --build","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i typescript -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.0.1-rc.5959+b90a495b","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^29.2.2","ipfs-core":"^0.2.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","typescript":"4.0.x","uint8arrays":"^1.1.0"},"gitHead":"b90a495bd07cc81ac7a9dcad75c5625b59dc3dd9","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.0.1-rc.5959","_nodeVersion":"14.15.4","_npmVersion":"lerna/3.22.1/node@v14.15.4+x64 (linux)","dist":{"integrity":"sha512-UfLhHKUyUCfIv/HB5FJ0g+31UYd+YjBDZQ4KzGQB9BEURnWkwdE6gFRcwKWLtFfT3WF/Ip7j0Bz0rUUC5TtZDQ==","shasum":"c7b032948794a4da4b5c5c9ed7cc2e26b98fbe03","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.0.1-rc.5959.tgz","fileCount":30,"unpackedSize":129608,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgAVeDCRA9TVsSAnZWagAALOgP/jZUWOy2z8aMTbhAZGhf\nm3YIs0ZjsY3QHOXiB41iRbOLKsJgeQXZlu0c41pM/TjWs1nrepzAbQEIrx8M\n3KG/Gn4kJQr/IR0SH5N/Yhwbp5baRySuf56yl3x9UO3jA6IdvS+w5Un5yGSZ\neiFDTglH0tYdj/BpdQS6up75lmQj53WtHDNdYDkS+ZotQzhI2XkimGeBAO09\n+qd/nZF2B2KDK+lgXqzX0lDcEhmmk+Z++B0P9uXvyWL7MYc4AOauk77vz7rt\nvm8pn9ZlTUasCGMDXZocbTXf7NV4cxHieF1JwZR52qbQjERHRMAiH0/fc3eI\nQu+YEFmRaXI61ys5f0QBtiLgvCljKuA/dN3rC7QGFSWv3AbDsEgGqlnVH2M4\n4P/2XnQgloxSMW5Q4sdmUewZLfnZY53KEdh4YXSJHAQVNS0Mucge+0sUjTFe\ng70j4TgZseUaRdrmVSi72gnnLo7cxSp/nXrFmbA0eynOFd7sVX+Yi6xJvi/j\n1dgSkTY9ECSUjFddQ2uIDd3I3f26Q8WjWsGFLln5dusFKjzzFh3n0vodRsF2\nm9nq8YgBqILMAlzZpNvItkZe7+eOce7KY3AMwr0fR+cb1eLIcNPVo8EIBpuZ\nbZm9DMbUoYw/0/fm2DKiJwzQ7tb0ttj6jpQCjuAz0DKotl1j7IhA9lUGBgk2\ngvcx\r\n=VwkH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD9ZAJyuGO7FXwHXRnIxQRUSCE4UzXS34nFTnOHf35qKQIgQxUHTVGhNFviHCR8ArxV6PBCAXCRtXzGfbzNpC6SYcE="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.0.1-rc.5959_1610700674788_0.946449414272496"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.1.0":{"name":"ipfs-grpc-server","version":"0.1.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","build":"npm run build:types","build:types":"tsc --build","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i typescript -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.1.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^29.2.2","ipfs-core":"^0.2.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","typescript":"4.0.x","uint8arrays":"^1.1.0"},"gitHead":"09f6f0cc98e2b8b2f1dacc69c9491555b507da28","_id":"ipfs-grpc-server@0.1.0","_nodeVersion":"12.16.1","_npmVersion":"lerna/3.22.1/node@v12.16.1+x64 (darwin)","dist":{"integrity":"sha512-6u1B8hwF3JK2OeOmCO++1eFUcPO4QpBTWJZoF8HVYg05UD7j4vBnoVbR8Yn16BtF1/iRxNtZvH6obpM4LqyoXg==","shasum":"c97dd4b54683a463f083c18f46b090622a71f861","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.1.0.tgz","fileCount":31,"unpackedSize":129895,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgAX+yCRA9TVsSAnZWagAAPUEP/1hlOHsQnvw1KZmWrGLP\nyXGxA+Z85rxS2eCFilVrDYrCzGdizBxctwVKAL52GQ92z7Bvjpabg55JgpM9\nkrY4lGM43jNjSEk3/FaZ5GqzLzgu07Pq+PBgypDl31MjRlnWCe6FQI7x1knd\nzuQGXDKIIfCMF1GD73HaqZTClDsIPWSgzE8oZiF1soXXBnGnFiewGONY6aLq\nwoW+gz0EAGSundUYs6JNXs/k2OYTQbwKdLrXA9Brz6H8hdS7YxTNbrz8RlqU\nIkAQHaRYokWpcSqDif6+huLWJ0sxQ23uNWn8GJw6xWFecRsITdntAJHc2UD+\nG14YgxTQ/1snHUXD9k+ofbztqJX5/Li5MIg+LlVT4drwHhHvXlmVGgHSytpZ\nU+yE18g9rK6QtBPFlKJKckASRubTUr8CpDW89HU6Em2uhf7GLFNtcSk4MdR3\nkfuPmb7BrU2LCbbLWXSzMBuHwY8pJQwvsfNBAjaHf+RTmF4WNVdfrTLa/G5r\nhSvWaHltZbz/aAyKyJFYFjBtcp8H7ru3GgUl7qC6JALpCZdHXeS+yLHfJqDN\n1QgKd76ZyAFOuxBeltNPh0Ife3r81Ht9SdSO46iUvfGbl/npjax2de8po3qc\nXWVvEQagdM42BRS2lc3Y6diz6z7J8SYa8Hzm7fcqNEoMnfN1W7bt2ewQ5SRb\nwWwB\r\n=Xii/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCHIL34+NtdRqU9s/oNlRh0VCOCMFS8ceN4q6uzqNBa+QIgSSLadxIYyTZ9GsH/EQpSXOSR3saOKW1Q1fE5O7eSmRU="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.1.0_1610710962371_0.3243024452651351"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.1.1":{"name":"ipfs-grpc-server","version":"0.1.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","build":"npm run build:types","build:types":"tsc --build","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i typescript -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.1.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^29.2.2","ipfs-core":"^0.4.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","typescript":"4.0.x","uint8arrays":"^1.1.0"},"gitHead":"43d5bb0318cb840814841084c038f77562ba0d98","_id":"ipfs-grpc-server@0.1.1","_nodeVersion":"12.16.1","_npmVersion":"lerna/3.22.1/node@v12.16.1+x64 (darwin)","dist":{"integrity":"sha512-SyLX5lJBrQdJNaIJhE3v+29lijcN3BqTwISieudCmHpfGjhhWKQsJjX9pdEd370JAT8616/1DeFldAhuHGDiqw==","shasum":"78a8d2a54c51bbc0f82459f97566e3d0fda411d6","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.1.1.tgz","fileCount":31,"unpackedSize":130315,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgB+CQCRA9TVsSAnZWagAAd68QAJPEgZ4tDt6WLc5p9EAj\n743PFAXIMmPGeCju0MeKctmi8zYOkTXu017Kx6BJfCYgA6ncqnGSRLHOqBB0\nd6DAFvrN+BfzrXiDMHs1LUzL9CV2GfUbKb27ZQmRnmg6MjOme+0VUaTtDBfO\ncaIMr39Sl+4vMyN5jLH4ziCEmT1CPcgsOV8qzMCcC6PKYfzaOlOxAR/GUiyp\nHJnQbLBjAAV2XBnQTK5fyP1sWA1YwPcCAMvlZGH7tugWjO5UT8wvCMKOn+xQ\nGoB7772fyFKqVeB+mHyfoNSsI0lT8KVlrENrIIwloJ0A1yqZrNU3ZYSm8jrD\nZRzgmlQ79/5XIYzjBPjkqXB6U/vQN7jnGgecEi05CxXwJ7Zg8bYtblbpOdGf\nglvowcCXjWeJ3nNemGR2MSDxZLUr98CzRW/PwLHMF+oyzjRZn3+YnQ6JuVV8\n7sVhxlrrfydFT+AjuFqa4Em0H0OCHsPh/R5oMmZf9TwTuqr1JUfDL5tzo4Fd\nuHYrCjWz9jkPIv/2paB4d6wd6oWZwsqGEi4nnX1zGsHzFMSQm73DXDiZaWJ9\nIqC+1sagOh9xC+Jp2rheLmQ/9WesKPi7EFLjKVZPLQAjCPrKLxUw8k8xYgZp\nUON5eSP3yCzif04Dvl7pT5I/bPVijFt2KbnT7k3Fs+6sHyeqvp/VOWWxpr+E\nhKur\r\n=5DDT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCsf5aTrPu4/BBfyD4yNZS+lMf5pCIrIW+HW8DOEOd8xAIhAO26DiSUUVBwd3yGlTmlmGji8pB0/9in2sAiMS8USfT6"}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.1.1_1611128976511_0.4098879217452107"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.1.2":{"name":"ipfs-grpc-server","version":"0.1.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","build":"npm run build:types","build:types":"tsc --build","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i typescript -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.1.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^29.2.2","ipfs-core":"^0.4.2","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","typescript":"4.0.x","uint8arrays":"^1.1.0"},"gitHead":"2f526025a3603026553b320e050e57e2ee564562","_id":"ipfs-grpc-server@0.1.2","_nodeVersion":"12.16.1","_npmVersion":"lerna/3.22.1/node@v12.16.1+x64 (darwin)","dist":{"integrity":"sha512-Khfmta09mpHQkXyG4SpeNIcnPNtUo4ZCL1P/vrxxZMc14Niy6VH5JSmV2b4vz1MgywTpl7/JiyArY5O6JIHCnw==","shasum":"8872c98bf967ca224142662d825b503fc1e6987d","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.1.2.tgz","fileCount":31,"unpackedSize":130522,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgCr80CRA9TVsSAnZWagAA21cP/1a+wkka8y3LadcPNvDt\nFgaPFfSQFDmqYWBj7Nnk1nTTrxXmGDsXQqCZD4vPzuwhrYkPaR/PstA/dMHl\npJ09PMYZqi6w/oPaYYaj4j8XPT9hFz2F+PaQkwCZZFUcaPkJ6S/3mX7OUROT\nv7RZRMpTuJkoB/0oBh2xsyqTctbq+NW4VH6lBYgpV4mkROJH319Y+5Xuo3sg\nnv+HaH6Dy+MREcAfjU393JWDF8P/vN75+ti43YP7eoy528keKxqd8nDDAVLk\naC/LZOpW/ucXKjoDEiDvooLgqHprq2DPYV+Ptme1iUczaEwuD6f1LImyneOq\nqOmSkDvBZVT9d4b/YFFDdzpj230pmCtrUHu8YcT2jMTzL70SQnNPcynSNlx4\nEvDnndGV54pE/mIHC2fNq0NGyFafsrt7vT2e1l8LLWol5f9la1fVJs0Ra9gz\nxzJ9I82p9MGYXjgxK4ae9hhKbpLFYxhZvQ13j7EoNIEtuRA1OvkxTBRtBHks\n/cy6Xf/LXuNJZzSLkihCSPXc+x4Lf9BdAua6pRr1ol3IOtfEw3FXMsAz+UFF\nFUKKcx+g/MYpmqPq1tUIemxSRpj2/OeSD+1huaXdUlhG98n1D4MJYvv2tde7\nOtVc5FkAbDXNKLDtdiRY6zVyBSaOp7bIzrSIHJdJbIP34ODevZWzUy6lOyKq\n1qmb\r\n=clTm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDWmXwYYEUSMfynaWMxHf2HyAwf5DSc5nLteLMcXNuhOQIhAOAn5hxsZ4a1sm3vF7zpEnJkTysvgZpY0CahKDr0D0qL"}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.1.2_1611317043767_0.5219620879433131"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.1.3-rc.3":{"name":"ipfs-grpc-server","version":"0.1.3-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","build":"npm run build:types","build:types":"tsc --build","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i typescript -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.1.1-rc.13+6ae31055","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^29.2.2","ipfs-core":"^0.4.3-rc.3+6ae31055","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","typescript":"4.0.x","uint8arrays":"^1.1.0"},"gitHead":"6ae31055d21fbb0243bbb17cc697ebe18d84acff","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.1.3-rc.3","_nodeVersion":"14.15.4","_npmVersion":"lerna/3.22.1/node@v14.15.4+x64 (linux)","dist":{"integrity":"sha512-kjP9e2WuNAT2EWmyd42i9tLkh6NiCkvU4WMoN5ixVS1qW1lkbvhyPd56XpFBIyIlrd32tGRGJIQEHFOTGAKzvA==","shasum":"d49703dbc6a30dd1c8f2dc58a37d5168a9b3e148","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.1.3-rc.3.tgz","fileCount":31,"unpackedSize":130743,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgFRQgCRA9TVsSAnZWagAAiX0QAIJZdbZNVviQYK+ft2GZ\nNAtJ3hkQmBnl4NcRRT9ZjsBGH+PpTGq37iQfv/cYZhcMGrNOfegjUFebJqC1\nBd9IB5TE+Gi9OMOf7DUxB57YoaVRe7NjH26no2hFCahfa2KlgswWhiO9b9DD\n9cN/2XgfLhXsIkh/R2pzjbAN21ppb1NIuddxd0Zm7CjdrPFaR+1JXK97ePcA\nx59sSNCXxdzUULuKDVICcfmKzlZgWjSV4DUKxndPRT8PQLj/SAWq3dSD2zmJ\nPgn6yHwcWl0vTKBa5Zx10zGXUHtfwy4pRdaSclicMuL2BjHorDdriFXxiF+e\nKo08x95Qf2A+6HU+OfixlGxFzeaxIPgX0we2tOW+TaeZ007kKwhHPXDPYsd4\nfYe4Z4H4lgvz3AQSB/DoIlHnSaXCFgN1rewi/FcXDikouR1z+jnB3XXBT5zd\nvpV4kGWALNEcYL7BlcwW9DvSUWrosSRUgEYDfVZJGlvjRBzDefpFhQRIsmG6\n78cD61mMXecVydt5/S8EV0bePWiL7jLm6sVIMvdro6hPZ64GDRjEf5UZ4IaX\nBcbIsEhSxNqrlBI5yhJEPaWDd7qEI4QHbYjUatn4rOntoofOEtf7bzgg7cSL\nbBDr++SN7uuCNiaIeOkTo17l8wVfSIRoDEF5Fhn/encQBC39iAAB0T/cZmWy\ntFXh\r\n=xWyg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDvJdXAr94g+Ea55gUFDQoikj9NoPN/on8+qPsv+pBBnAiADyWmYk+2SR3f2NeF4tGjHYpK58ShB49sYOcg8az5fUw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.1.3-rc.3_1611994144347_0.13455671031889582"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.0":{"name":"ipfs-grpc-server","version":"0.2.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","prepare":"aegir build --no-bundle","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.2.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^30.3.0","ipfs-core":"^0.5.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","uint8arrays":"^2.0.5"},"gitHead":"91df29245562d5e9ff653e09b54cd2390538e64a","_id":"ipfs-grpc-server@0.2.0","_nodeVersion":"14.15.4","_npmVersion":"lerna/3.22.1/node@v14.15.4+x64 (darwin)","dist":{"integrity":"sha512-qVy0iiCCgi2Mt5lUM9bdLdNY230FpCsa5KAQkyTXGFugFfK5pj5/zZmqyZCqVoteek9OYwk8n59fVYFN+60Vzw==","shasum":"65da268acca1b3f49fe41f6f154d2084e3893749","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.0.tgz","fileCount":30,"unpackedSize":28225,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgF+fHCRA9TVsSAnZWagAAF3wQAIj8046S0Yn/OaYZWyxt\nMNOFv+zA3wh9l2RHQnNNVGGTSBGIpWHXNe9AUhuME1Y6EYpMiEsCQ0JjEunb\nMbgefMR6301TxTiwrYhxRx5Xnk/d1QMkpZ/fzayiWl4ijLEnZeRxJTWzT6Dn\njLnxRZj+iXXkZafJfa6LuMU9so0Gu4mn+MbMQyv0RIMLBNKpLK8CbRw8ZBoP\na9nwni59ywLqE4bL0J1X7ue0KM9ic+m1t7/37r1hqQ5g3EK66VHCLh/AJ0Wi\n7RSwqzvPv6x94zrA/Zq8NDDDoxH18TkqQtKNMV+j/0+zzlC0QNDHyTv5S13/\njP/bsyuM571E+maVMFb3hPnyF4yRvSolXRQSGA/NHoapsebheSSpnym3hJyN\nSE5lgYA50SRQVzY+WIM/4UbH8vjzTr8k2p/Zotyi+/Lb/tP9CKpjwVacQ5rO\nuKZj5vH798ho2+BwyfDnCTS/4j40qmPjoHCK3Mpbod2wba4O3WTtD/m+Qy4r\nhT/1T9hAo65ilDeiYbda9m00t6NXA6cd+PbYn/vxLDKL7VtPx2AjbH22Ad0f\nsEu10P6wEEn6rRvtOCdSIEk5Dyt7W/f4qztHZ1RnCwzoRa7yGfkICVPoRf86\niScvpvfqM9G3Ai/FRUUF3aaDQbKDdUBDKWPevxXuY3LvktPyiB98IFsVYWCu\n678v\r\n=RNq3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGuvXknkyN5GBdFZCCCmi8Vm9LFjExbvoGZ5ACSMX8EhAiBrlQKLHafP80g05+12Dr7JOv6C5sf3qp7MvIanv3bwhQ=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.0_1612179398687_0.0832127445960098"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.1":{"name":"ipfs-grpc-server","version":"0.2.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","prepare":"aegir build --no-bundle","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.2.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^30.3.0","ipfs-core":"^0.5.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","uint8arrays":"^2.0.5"},"gitHead":"10fc290deca311263a4db95ec6b9e9ce132d6eb7","_id":"ipfs-grpc-server@0.2.1","_nodeVersion":"14.15.4","_npmVersion":"lerna/3.22.1/node@v14.15.4+x64 (darwin)","dist":{"integrity":"sha512-cz67ilqYtrdPWQ33gjRiyn6wqawm4wWKgjv3OLC6Zr6319IIL5sOgiezVgEpsgbsCyzb950pcJ2zIcyD2RfU+A==","shasum":"e7d5e50d28857574a769aa94c88bcc4eac71dca6","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.1.tgz","fileCount":30,"unpackedSize":28401,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgGRYcCRA9TVsSAnZWagAAq8kP/AqWJr0+Q0cAvktDgpHJ\nzYx8mHxkUuIRD+n/pUOOLeAEeSeQIKmbKqAenfpG6jAKZdfADsDkjAWNurdN\nOKPAMEqt1f7l234e3TFrWg7h8KJ1tQmlMLD2LuuP6AO0u85atMxhgzZFjwpM\nuMY+vIVhxFGIMRxKFFC7ZTJ1U9U6xeaexZzPjMPc7UOfN75iI/qawTVGysWq\njYv44dscDleOxX/GjNyHcKjRtyyyFDlo/u/XxvAu2VBxXXhW0uD0/z5MERFF\njtSln9QwQLr1Z0Gj67ifQdokHrgoR9yk2rHIkH8H8KT+7dAdbjTtRmoV/E/v\n5sWO4ycGU3z1oNQa/i5t6Oxpx8E6aoetfEW8alCMiseQyWy25JGWI2sa08OL\nktjDTDPsq7jwissztJc/9/LtHJwrwRNKW3l8a2C15FBgEF3+e2CroN+QCyTH\nxsj1aRBwXZ1Tv02tjTi3bem7e6Ai+wwe6QCDQP+bTWXV1Lxy1hIf54882WPR\nR/lSHmyxvYqfHpFc0mEdwRhjOyTkHSFfLJnuA9vJvfDFXxQkqM5c3srVJodY\nRFNwp/D4JcRI7GpJHZp8gM+51wZLlrmAwf7nSbBXntGJaTLblVQU8kbfCg5N\nDdeVX1g9k7z4kk5vfRGhq3vwQdxqOyTWduWXT9dnSuKt8Humkq6a4ySddif1\nvCBb\r\n=33/c\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEyokQLdlBTk4+SazIIdzyeCmmKXigtGuqXEfqFnyeMCAiAcNSd5X5NwUc4zhefaZzcAEcYWkx5y82j7EyRNNqzIWQ=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.1_1612256796046_0.8887812821704022"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.2":{"name":"ipfs-grpc-server","version":"0.2.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","prepare":"aegir build --no-bundle","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.2.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^30.3.0","ipfs-core":"^0.5.2","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","uint8arrays":"^2.0.5"},"gitHead":"ff76e7cda441d66d327e03e3ca1dea6e901ec918","_id":"ipfs-grpc-server@0.2.2","_nodeVersion":"14.15.4","_npmVersion":"lerna/3.22.1/node@v14.15.4+x64 (darwin)","dist":{"integrity":"sha512-WbxYcO+/KuGoNE2ZL35KXiyjRBObqKiXCW7Re83BLv6wF/a9DlIojS46eJxtlwOAh7saOpq4mteRFNxx5ACRMg==","shasum":"c3ea3ca5d0c5e8b50acb2a64a973f0c1bddca8b1","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.2.tgz","fileCount":30,"unpackedSize":28577,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgIVnmCRA9TVsSAnZWagAAPtkP/RZtJl2W9JU8v0ki8FWg\nUHHlzPSjBt2Wxuz6diFK+BnpNYPPxPuQa9/sYhth2sDET0bkoUzJ0N5rLWUX\n9crf9kQYTos4JINQ2D/C3bLo+td2z6sxgarn3l28u1YeUfWHOdlaoJFRyuVj\nblVgIkh15MavLbQhZDKYA1EjeY7h/MSltxRrQZCEijidHt8IAkbWX7fO58zr\nQ3GLFSVgYK/v2rPzbrxMttKcgaaYkRUbM5ZyXYF61xgCAjJyQlyGyABPJTv8\n0iu7NGHMSSqBGUp41mj2JEwJcqiNWRAd7Xo/7objy+9294SLAhvEZrwJLDA/\nVMQLiH7nQzaU/hvV4fkJs39djTQYyiGzrZD9U9lJHKspthFGps+XfRFOtmWG\nUQaGe0d7l+isJV+e06rqUgPwZKjrDlSg/jubPHbycE/8cWbhynkZ7Z/6VO3S\noN5/Ao2KgBAWZ0BswJqXrgD9KIsAcWN1DPIxGh/3u7ejDu9hJjS7IiP9WgrV\nNtbex9HNicCkdq+UF2ZLMFJiDho4onaEClCnyu8l0omdbKYnJMVGUQkb/2Cg\nMRu/OF3rhgQ2zNPjYTSloDhmJn4Fp0Fv9cqyE+C+/Se32Zy8AcC6BW8vHsJF\nFoIWwc/5MGDiiHV2IT6cpVmBSUb2v+Hd7NccfuqVHti6CUxjAvJLn08sb2lx\nKqTv\r\n=7ZUJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnlu0KIam+xi5NNKv2Fy7iufPIcNzT9gtN0X5jsQYLGAIhAN+Q8W66uXoMabuwZXuhGgGBjjzJIK3RQmfnGnWkoyM/"}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.2_1612798438076_0.6561427989124233"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.3-rc.4":{"name":"ipfs-grpc-server","version":"0.2.3-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","prepare":"aegir build --no-bundle","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.2.1-rc.13+be0c613c","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^30.3.0","ipfs-core":"^0.5.3-rc.4+be0c613c","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","uint8arrays":"^2.0.5"},"gitHead":"be0c613c0e413077bfccfde0345b1ff2471193c1","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.3-rc.4","_nodeVersion":"14.15.5","_npmVersion":"lerna/3.22.1/node@v14.15.5+x64 (linux)","dist":{"integrity":"sha512-xnW3ZhS/dytxgT6CiHIVO1hSe5a9mXPsMWoSr/RQeQK67PMrpEbHdQl5ZHEEa5K6GEJHubJOy/K/AVXbdFnaCQ==","shasum":"4419adf0b3c4c6612762c900dce9853de6aa12dd","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.3-rc.4.tgz","fileCount":30,"unpackedSize":28620,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgMiThCRA9TVsSAnZWagAA0N0P/i3r/TqwClrAPkDcUm69\n0EZjZ4bCuP7RMhum6MM9eGXplid84GrEI+mBLMxGp+uTZQeB5h7F1wie3FbR\naYkFRDfLD/gcY6d3bAbwcW6n+/mpT/lyEZjiwWy/GMn/ytf5NYdY/xjxbrPL\n6/WPjRh4TR1sevd8g2+vLw13eqKRDcM25PlQiDiDJggzJPit1MLT6VQURxAr\nEAYosRY42u1TFsanNtpPDdgr3mwe12c4uwZYs8NtmP6oHGk0aW+cQ9yPSQLw\nUtCEZ3gzJ0rwzBDzQ63xKXTsYjO0JjbS6lUt+T8+7RpepMYT+Pj7Qm2BHnxJ\nlZHdEcrCblck3MhWHZQYDW/t8JCHgjmiA1cMY4dus1AJUOG0MHtP34sbGtr2\nx/F2VJ94fMWICV+btuxCH0C5LK8cIChvPy+MnZ5abfXib6RpOVYJTeNEH+l9\naTtoy2RrI+ASH/LxNW26RfH7Y1oMtje9p1dH7eOOYLoiSvKtFKPwCaqy/DNb\nGEqPXoxRi9k9Iwv4o7DHoOR8H7Zs7Zv3wF23acsZtBsHn0+wfGFKNMnrOXvV\n7j+lBF5klW3FXzstwj6si5cauWUsibZmtJHDXCKt6/p3i5WoABVPnZIvi9oG\nRoyUwy3uGh/OQMdjyvbK1aj5H33mDQ0/nyeODuK08M81tZqU8WBTCkJzEnZp\nYwfp\r\n=TJno\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC+QQrPZZon/M5ZSk7YT/bQcP3wxHY34co5DMP5HNC/9gIhAPG51+15H/xRaDIOVZtjpgCxmqMOjB10ubn3Cuq/lXdT"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.3-rc.4_1613898977157_0.5212652439364807"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.3-rc.5":{"name":"ipfs-grpc-server","version":"0.2.3-rc.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","prepare":"aegir build --no-bundle","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.2.1-rc.14+b7659d45","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^30.3.0","ipfs-core":"^0.5.3-rc.5+b7659d45","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","uint8arrays":"^2.0.5"},"gitHead":"b7659d4544fbf335eb5dcd3b71fc1b81f436088c","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.3-rc.5","_nodeVersion":"14.15.5","_npmVersion":"lerna/3.22.1/node@v14.15.5+x64 (linux)","dist":{"integrity":"sha512-p1ydTFq6aSg5AwOK29nSxp97+Q2SaCsAAyFwYnpCNcvjh+6hMdOMkYCmBb4IkcATlOMTf8oAXKWW6tZy0/wi8w==","shasum":"77319fb86441a9488aa9f4257f095fa0550bf341","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.3-rc.5.tgz","fileCount":30,"unpackedSize":28620,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgM97XCRA9TVsSAnZWagAAv94P/jooGPeILxhenRI2EkyN\nFn7KBMFLOv9s5k2DhMtOr1B2lXiwx7BmEDthhfzvibidPkyc74O8CFwrquoq\ndcIMiEhUr+66KTr7+3iBnHw/VsOSF2OfSM3yhiU0vSzIDFLw8nEFVUDweUMj\nsvZ1lHaF1NU3QxC/TNJQJxpnJDTvswUrVqJedYPsQKtBPpDwPQeF9cveuRxb\nMj7qwFyWzNVDHozgZhZwfD3ueT7sTVJbmsn/pIxrv+NeDELySX5xaHNaMKXo\nrC84vPTH0RZuD3J0zwaPJFER2gbO5JVL6oPBMRtJYscZLoE21N/IJJ6kEGj2\n5LfBAT9FHN0K/1ZvaQA+Nl4PGmAlMSIuO0oUtt5+j+cEgwgGg1B2tqVRESWZ\nJ184g1kHi6k007gTzDK3s5Ywx5N9OdQ9yzKqsopf/Wm7XcVfKulMyj8IJzji\nYpD9KzlU7bdzPUvTNZ0StVgEM0DnVtNzwofbMi0JErtgNnae2RZP/YEI4mDA\nKV2mnLrPJMr651tGRdq8H/WAjnBhHqqt6e32KdhQ+rTtavDHtD878BF34vqZ\n/jjmPjsI04fndWzrmZOEp38twY9MNXOxUrbIHFgs1sXZfuk1beRMu/MVPPH0\nUNCpyOcbGJfv4ZnV2n3a9XQaXV9TkBCawjccXwldWI5uVtC7w0St5w/0wTA9\ntALV\r\n=lZrO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGP8EZR7JWycs+qFAFVYskrl5lz1UYr5wv3Vo6MNzkKEAiEAsa9DnP2Cdpxjpmlo7roH8i8YGOc4PnuoXWTHOrpjosU="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.3-rc.5_1614012118796_0.14502928134152437"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.3":{"name":"ipfs-grpc-server","version":"0.2.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.2.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^31.0.0","ipfs-core":"^0.5.3","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","uint8arrays":"^2.1.3"},"gitHead":"0af3b76115fce61d64f0f8be90cf13263d2a12fc","_id":"ipfs-grpc-server@0.2.3","_nodeVersion":"15.11.0","_npmVersion":"lerna/3.22.1/node@v15.11.0+x64 (darwin)","dist":{"integrity":"sha512-TD8yov2zd/g5Oj3h4FwX2m9F7QUUw5FArPte4ODDd2LnQRWuWEYVl9ox1pdN91j9UtPx71aa0TN/gGt1UlvN8A==","shasum":"f643f78e536e45c1ea356c610d1b22c087baf054","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.3.tgz","fileCount":31,"unpackedSize":177447,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgR1I3CRA9TVsSAnZWagAAojwP/2DPOxk7JHe4U4K5lzfV\nQqKo1V0Y2fHjX9fzamdQLRjNKJVR6Tk+o95xKQ2kxKRjz0ncuUkVq89JKjLp\ngh9VT1A2KORzZ444rLykdfViUqWeF2SdWrgUKcrxFja2x6YicCN8X+U8aSVV\n8UvhiG36W0FsUaWGgC7M33bo/gvorbwDlUfLq0/RKlzco315HBP9tz3oYzfF\npHZjn8ozC8RrDSw7KZh2ZOIrv928CN7docxJukMTj2O8VyCKc62+WTa8N2go\n8hDyeWFasQEAtIcqasff886eV2VoajOSPsBWArEDoQjKy2zIMtu31HgCwjWN\nJdZjmCgpjMrP7kLeBv4LoUYTZK7f+TghNMCCjNK9VC2zJXTKCQlYvJRe+KwY\nprupyCCEGXcL8efgjG2CnS6HiF5bnOQQWJKSrg76jHRnaF8T1A/usgTYpPsw\nJBUcAGhI7G+NUcKI7klrPheMiorlfc1G6XNXIVRKNnY2k5EQufAp1uoLWYbZ\n4VwY5Vu55okF82bnBw0sR+0eZsVgbTW+T5NR1qycel4EfJT6Hj2k+aedLyZg\nzmS+2kc8yjfqx5GxplijS98yA/NG5OwsUSI2xdTC4eq016rRJMbN9EoctvMU\n474EqO2uQ2Z9iZ/AuJNAbtfKa5yfLtyVQ75GDONlXJYD2XaKTI57lnERjYqn\n0VV4\r\n=PlSC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEIi8DGNU6sPdrSBYZj/wZu7Eh+s3DBBKgkjv2csHctpAiEA/FazNBwgCb4wl8a/96U/y+RA9gaGdhe0W7WAwtd9nMk="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.3_1615286839147_0.8934144053990627"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.4":{"name":"ipfs-grpc-server","version":"0.2.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.2.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^31.0.0","ipfs-core":"^0.5.4","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","uint8arrays":"^2.1.3"},"gitHead":"511147bedd51be3151de44a90fefe9425bfbcd50","_id":"ipfs-grpc-server@0.2.4","_nodeVersion":"14.15.4","_npmVersion":"lerna/3.22.1/node@v14.15.4+x64 (darwin)","dist":{"integrity":"sha512-4MYFjkWsgq7Vi3wAXuvUALbWl6k1TFTsmbrj+e3Meh/Rpmp2CJ9JyZQB3fxEvXsrBjQphX45Rf0KAipVoImpxg==","shasum":"480f4c08791146635679d7a4931dab0e1c60a9d7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.4.tgz","fileCount":31,"unpackedSize":177022,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgSKnFCRA9TVsSAnZWagAA0nYP/2oH1jYVi7az7jggxEZS\n6g9aY6UbsfvBJJspjhr7wEyPDo8cZgJ4Y+lv5LDLcsrB+vsrzbspvG+JsZH5\n8qPYRgeXj0YTS81atBIo9t/RVRFUkLNfPjzcvSPNW+znEeqGGRgc3czA6yK+\nMtNbAUbCE4nUZOPcqLUC6hTM1845ldHk4OBQoj3GMDzfSbPbw/WSbTonEM+Z\nyR/59Abl04znlwnDDQ61c+a3YpZB0EZodMzYjv9ToE8VcFyee4q1krpc9pcm\nWJs/+YrsDAAa1j6vRQmZMmKVaJeSt78bqH7X9XzL6wPGrTQVni8hQRiNCGXY\ndlVZr2H1FtYbCPloHaCuHiclxtn9C4N+tFbE8YRtOuH+R+xNCEfW/+t0DGO9\n5MCqGvSlk0UBT1hQW75vefEjZ8dYJkBuBnKzzxocGdaL+hoq3jl7Y26tTXHX\nXG2A+0pqD0Wliaw5vRh4737J/bxL84RLrHCLMRPbq+9QGvPLa1wHp48SRhGq\nimm0LIXAt/RyEtdHOVMAvAX6/Hh00P1yT71aDsqLZ5WnHF3tDZxOG2A1n2Uh\nBDsrc878CZBiQdsCwQZrXBI0KEhq/PyQWEmvk/AShZ1AcfPvixlwdhsKW/sC\nHbKwd3daJzaaom84eR1o/pOarK5dn+MMjzzX+aFSxZ8h24W/0LUDmUbjQGNG\nCFv5\r\n=0PDE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBj8RaE2ZsMucO/ChT+dM9dECYi0mWtM4xvndNDBfbhRAiBlbev+kNr7prl3xa99VSPKVQ51UuvNodYDshQAgaQAsw=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.4_1615374788695_0.6186043726756882"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.3":{"name":"ipfs-grpc-server","version":"0.2.5-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.6+1823375a","ipfs-grpc-protocol":"^0.2.1-rc.26+1823375a","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^8.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^32.1.0","ipfs-core":"^0.5.5-rc.3+1823375a","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","uint8arrays":"^2.1.3"},"gitHead":"1823375a17ee2562f06accdd605eeefebf7a3922","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.3","_nodeVersion":"14.16.0","_npmVersion":"lerna/3.22.1/node@v14.16.0+x64 (linux)","dist":{"integrity":"sha512-hBWfeC9O1hV141SCcB112VXvIyPFVie9OIjtoCCW6f8jh4JE28q/rCCVQzJ1DH810R0FcansN7n/sQjRc8A+Aw==","shasum":"9a76a425505c19519f58cd7fb4f2edd02d80fa02","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.3.tgz","fileCount":31,"unpackedSize":35298,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgZJI9CRA9TVsSAnZWagAAAlYP/2MKT7so3O0leUulh1LY\nQGSj5c2pvca1gb3NM5Hgu0g5CfZmb1ruwU5eniS0CooyxKdm+FTrzLIUgXbO\ngrJIZ+rSdkkLvsDa79dTqz+VtothifupxsKybTYBjjV7hYrMRySrHl+A7P1r\no7QtPzTW+VsKkAcY/tAj1I+mBkqDoicBVP/KcDc5CEq0tY3+f/aHD0WL6og0\ncvTPfda2Xnckk3UuGycnXrnmR3lHmI+KiFHhhJ1JJWpI67Usu9mMRU99pYr7\nYOVOvGuwqNEsD8VtVELmPqkB+QmHjuTJsoWR1sXnizxWTPAWSXlz/7CP4AZs\ndhhqCzz9G5VEO7GHdegIhiB3irit4zzn5vVnGuZsAAgSPTdpQajBuqnI47yt\nZmzTXN30qPyBKZ5fVwBe/AVZsBwt2c/+OapkWaEJ43fK5lRsPctQDRjPRAgi\nTb+Y/eZv/oYRd32rgukMicL5af4bbMkskToSWZdcRgrSGYdbvIkRSVgXIDjZ\nyB8rieM6Bx12fTA0mSk7Yqz9gjybcQCJDFsoiT0iRHMcanI+d0B2nJL7Z3tv\nfNvZiO6Z2KFjAWRkcaKInuk7Epz6c78tN+7uqX3xisJD+vevi5y1M5SU4waB\nlG+3b9LwN/2kzx5cy7JoS9TyVRSL4HECu+1sMN/wXSDHrcfELP48gxKByN2x\nyhMD\r\n=5x8V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDKT/lvB81hYFgd/GRb/dfXs5oPvOW/ORxDAh8A6ykucgIhAOwDe6pWszjPmM/xX72yuE61LPNmdm/Dfx7B1hTgUt8g"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.3_1617203773019_0.9450783011559467"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.11":{"name":"ipfs-grpc-server","version":"0.2.5-rc.11","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.14+e7de593c","ipfs-grpc-protocol":"^0.2.1-rc.34+e7de593c","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.11+e7de593c","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"e7de593c9fb74bbb82731c9ed41ec5204b18b1f4","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.11","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-flM2Vwyafn/UTDWwgr63ZfSEOEwx/CBKMwkCGf6htb4MJYhOiXJXLV06dBAFuHS/NGI/9WoA1cmMfK1+VzEfMA==","shasum":"fdd454a52bed56b086e81e47bb394e164bd5e2c2","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.11.tgz","fileCount":31,"unpackedSize":35348,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgiVIXCRA9TVsSAnZWagAA1LQP/inrO0dzDFo5UAOsmb2e\n5ewTTymnNCt0HrABwxlHnTiB8c4jVsR2xcwCjodivvEsCysOHcSA4PgDXIYj\nKAWP21NGicEkTN3h7Kcg26EIx5WLFvJ92ajhdfgLr6nquG/wy3O2cTXpKJDY\n2XbknQ4pUKoXvdz7Yyf3hgw6TmOFadCmh6aCxcRPgCYhxFGGXNZ3cMTnD+Z3\nMYxI5JhqMdsOErIzCM2MS2ngD1FJ/N7KWp05Z+jaOK0zT9mPXqAkQGMRAJC2\nqDzomiWte4YVpD0v9Ov5HGbnIi4yDYBnlMxY7u7HFziE8A187gb/Hg2ueIGE\niqAo1+dnrKco6UdLNMwkUfgMUdv0GEXQP9X/a02xodQj1VEA1/fgZmzpdfYR\nYF4kMSlmx9r2CqALfJci/X/8je1t+TuVn8ajCrveXa98e34WTlr03q7vNHg7\nEa5Yvy9se3708VWt8ZeFY3wXyHqn2O1jJe8oP0xhkRSRLNn+P2I1VYZGunZN\nAr8MYh2UdQ2UGNFO4hsBBZnhGb0SCuGPvWcva5IrZqzxZcUEDWJfPo+QHBW/\neBMOz6GmcGC8r4TceUjtbTX77rAE3TstIGgdJauLLef9332AQSPIbGkvijuS\n/B6AYuT+Gy0LSVEntUfzbpljEMHQ6JuweVJnYwwWYcvMS8QjGlHzva23fJwQ\n+MhT\r\n=xou/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE5od9WXbj2opqfWxkw+xeh6KpvXHl7l4eUD0Jh8sqjxAiBo4uHrrJxHt7KGkRIP540LRmbOgpMlROHhmi7VaJf5BQ=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.11_1619612183302_0.19769819440690495"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.14":{"name":"ipfs-grpc-server","version":"0.2.5-rc.14","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.17+12915f70","ipfs-grpc-protocol":"^0.2.1-rc.37+12915f70","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.14+12915f70","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"12915f708057c54a08ed0b1f6c417eee8d65ad44","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.14","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-4XSmixsrzHRijBdL6FDoTgQ+UTVDCNJPhXSOEB7q0kcjKsl5V+lgRpiEpTs98hxub777oL6uVI2dmuLhBfOEKw==","shasum":"5bf929fe38378d84d1553da62bfccc82d1a3f08e","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.14.tgz","fileCount":31,"unpackedSize":35348,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgiZebCRA9TVsSAnZWagAAvoIP/3c+KsCaxdysVt9343pW\n+/D1ZYIzlM1zaPuzV0hrcE0hGVQlT78A5WsPHx0L4BjpVnQjkMeWwzXC74k+\nxYTcCmz3lpw42AknU5oMjoPrrFFKaeW7UbVkeTw7wQJfWk6trNVSfsclP7YN\nBMfmR8utmK54lpJsMlqXf94P7gUtHtlGcVgf+cpSCL3KYLv5vDWwAoG4k3xx\nP6cblG/s6sGoWA/NL8ivE9rFCGbOV+Wbz9vVWVwVjf1SOq7TLFMc3UX7+12n\na+qHYDuatcNoGxi2erGy4MYgkX/MplJ7YxEnbJA3A5Gtx0OfQam/Il/8zYrf\nMULJfv1NSvCoGwct6MK375MAE9jWczETtBi0I67k3chUdUjctrThRjU/gLqP\nrXGgafinR5Wp7LXsIraUvNzPdVc5V4NdYTcFuSlfRn+GtA+RUDtqttq15CFD\n401JvEjdFF1fhaM18qz1fDrhzQt1BhuiyFkAKQw8cO7h8RzoSUEBlq7f3lbx\nHy0kB75mRAFUA828cPdL9BA50mYN23hTZa/+vUNtiVOQtv/zGGCW+yKniiw9\nITeCTsWDC6hq5M5FIGdDkw5wd9T4IVfPf+G2uKelVzVPe2vgfUouaeuz2f94\nS+5Uj3eVle4w0aLVOnzLfseOMGDIePUMFYYYjqt3ld9anKGvxavs/870CW0l\neFuT\r\n=mIud\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCIkzew9wYBOcgYZ9qaxdzlAb3QzFYw26ztt4QnoGIhYQIhAO/qf9na+qUlTs9tY4yea0EMXGCdbMk81vcutoi18jpL"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.14_1619629979246_0.15179626504262078"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.17":{"name":"ipfs-grpc-server","version":"0.2.5-rc.17","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.20+99bde7a1","ipfs-grpc-protocol":"^0.2.1-rc.40+99bde7a1","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.17+99bde7a1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"99bde7a194e5918933e589d685dec222b083ac42","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.17","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-rHUtQBC0075FDANv+P3EfSIoKoi9apca/lMaG3ooEb4Mkqm4HbiJC/JYLITQqG7ZJ3k8VijpFgPyNK8I/PJSxg==","shasum":"859893b14724bfc1937fe9b17f8931aa299ca96e","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.17.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgiuVECRA9TVsSAnZWagAA6JMP/1h5uQtvvgkh899SiGGR\nVE9FEyt8R488zoP5PHH2L5Rq9MquQyhQDAPdfRERobiX5wN6S7n3s6YWSllz\n5uM5O0mVkZeii3Wd2Om4IZALI4SUohSlpYOVD60fxakwKV+1Tj8tIyguy6/l\n2zXO4KGO38UDaj/0vg228Qcs4hBka0s8U3HL0qdnda/bFONApJwqjpyjeBrZ\nDPvTO8aXv2n3feynZaF5UFU6PLPzIxJWUFl9kQnDAbVM8MJvUmDcT/+Qk0Ik\n75BRVxyZNmayxCjeswcC8mTU7Y0zQsFrSKHe+PW3xeq/Z34qnrLXL3rQR+o4\nFvJeJC1IyueGWvITC6rg0jD1/aHAnhvrl5dVThO6i3yYg2bgRHaC2fAWDWfz\nHSk/jZ2TRfkUKRnTr8ME6t/7s2fn7tW6H7MRb5Zr3XH3uaBAt8jO6+77onBv\nbcYRMCouvzZb6Jm2zjFsfkx9pHwzjmb733khRj+gNDScHChOIH5mltD1YkZD\ns5tg1Z4ag6v0VFmcTzfHeiZ6e1cMWCbq0GH5y7UJpj/Ze1qMi4pJRsWLL+q6\n2HZVJb9NWXcqRiB+JJZJH+iV0wowuyKcW9f7pto7p7QfC1lJ6EzPwuqIYuq0\n4lLhODfQornPLvZwr2o6YW9gVZklBz/AvWkUtI3f+YLRt4GjnM6x3hBtUbtr\n/6TP\r\n=r2yw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDhUB4E3IB0E1D6nwV2dY9a+jfV1vi9de7Ei3UGVJqGaQIgeibRukk83FXLQnOyNaqPn7onqRGH8VLaFbwKyZPcGMo="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.17_1619715396093_0.7100562653188682"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.18":{"name":"ipfs-grpc-server","version":"0.2.5-rc.18","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.21+2ec15c08","ipfs-grpc-protocol":"^0.2.1-rc.41+2ec15c08","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.18+2ec15c08","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"2ec15c083eef923096b30dd927801331e97b4f5a","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.18","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-BsT6fNlj3rthioWH3IgEeNKTjzlPXZbTZKW1JAl3b0Pm59PxV097aW2gCQ2qqAXOpWqsZJ7yV3et47XQnPPh7g==","shasum":"64a91ec925ccd715cd34b9f7ef349cb1284aec8f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.18.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgi8zUCRA9TVsSAnZWagAAgVcQAIHl3+C7X67PMIpO2K7D\nimh40xXtFZqI4UkcQrQNt5S7BmhgLXFEEBaOfBqFlNsIInI3gbxSeYodfbs4\nYx4vBLye+q9kJkUULEoOZKa26bT+NNOuvgQN0uEugmV5dWhptf4CROe4aNhe\n5dI2zwueBnPwcrKY4P+YqxbByJP6sR5NYNV7GuvB5nhjRsNqbZxK4xgkUZM6\n2r+pOL8KmU+aau+w4UgIcrLn5EOWNzgzO7184gSHfMTL2iLKWBsfRyPLG8FC\nAuJlV7RRiMJ3od1iT6mBh8qKm84KqjD40+MWe6s0ZhvbOUZEhFzuKNF51K5L\nHDZJn4Xt4T0R4eZR7m25EU4r9L+6GuQbiA2qOHKfkznjHju2+uBWWWh8aCzZ\nPNQOYfLxwQ913bPqqRVZLoSD/XojI+I3hZ01EBbb5dzKqGWycTGSxMjNWgZe\nD3Y2hzyu5UFqbZXhr354WVVN/c9mw4iNvdj5jaoC3gZtlfcCezNxvJNr0HMn\nYR6wCKIZoFOmWsm9b4CKgBYwcbyuWYuF8oQftIefh2HAP8MZsiJqEzhS668B\nfMqWIWIiYXAVzcnrSMi9xTjFQ9BnVmxEp8LmnmVE6AvOFLrAygQZ9KGfPV51\nsEOql5xefX/epKYYh+eQNBTQEYGb6mSZ8s6F31yUPxzVM9cUwZG01/2+8JCl\nvL+Z\r\n=qtax\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8rCJcA2nvZKvAJXw4zMUUDMYlJDdjMrdNGuQG1tUaUwIgAbVoYxZhTAjKEdH4KSfgCyPkIF62SDXKPE/uZR434hQ="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.18_1619774675832_0.9498995448752487"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.19":{"name":"ipfs-grpc-server","version":"0.2.5-rc.19","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.22+188f1f39","ipfs-grpc-protocol":"^0.2.1-rc.42+188f1f39","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.19+188f1f39","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"188f1f3930ce2dcea5a4fd6b6b1cf413ca04a736","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.19","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-tehWcsS1e5wlGYeLxYtdBvLJEHwCWWdaWr9JLsRO05T3T9Az1/4kXcVOc1otk8FhIUp/YRHRg7MS1YwACZH3sw==","shasum":"b5784ebf6b3efe209302a43b81d20ade97e4dbc8","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.19.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgjDi2CRA9TVsSAnZWagAARlgP/1ZMy9iZclZuqBGRfI7X\n94exOS7jGOAE7D5XQru1DYbDi5/6wExZbW439TxZtVkYMSiYBtjClPSCunoH\nTKs2PCTBxpwnk1+Ohgqn6fo71SaAWCo1tNf8sMctygG3J/TAbEtwZx8HhGco\nxKDBYSGeUWenL3t4ESY5cLMPN+jx7PA1wpJ/3dfbunW2LZOUXZe3sefxhjZL\nUDQfTrjcPg1YIN7U/jXD/4SR0rvlgDxcRAeCXipMI1Q0ajbDWNfGcHOuFFm/\nsPnqFzWNRshk+FvV8I2PXSMav3WvuitQ4y82hglNhGx4VAV5phifd5rmEsHa\ntiVVhd640jArM1ilspL4Xyz9qZGEhnrLcOrVH4TuhLX6rCu0Vjb3u1TTPKG0\n8AMHFLeujUPSQdTxoF2O2rKhNIYlvuCxRYwaZqJB0X+o8N7d3rzNIyE0frc9\n4viJHB3i+Ev3ESOh9YfDgpkQyJXTq8iKTe4i+HcIoWbhrH/Q7dlokz9YD8Ma\nkSTwD1USWg8/iJsZAH/MCEtuMMwT64MeGYV1ObxMrUv79p0W0Ztzfq+hVw9s\nNm8z1JY3akZQp5zS5WSyGC4tQfLZ9pOsvWKYs/fui9gL9pTm94DpZxeI0zA5\nO3UsxsS3oeQJ01DoWh7z3JfI0QQ05UnNeX65jXcd9gSP3YnHrwGxN+jJ9T6h\nNdX7\r\n=n1hS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGuZmC1yKg2tfKhI9VH019oXQpCH5kSKNCe8xTD1nNwxAiEAkxNoH467Uviry/XF7HpalYsBssBy0HQ+NfoWwH2tZoA="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.19_1619802294379_0.41226254362757686"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.20":{"name":"ipfs-grpc-server","version":"0.2.5-rc.20","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.23+1a447f89","ipfs-grpc-protocol":"^0.2.1-rc.43+1a447f89","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.20+1a447f89","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"1a447f893072d482d5a7ad148f9232dd43f64cad","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.20","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-fWQPA4ySX+I88wgDeb5aI80nH8LTUtZhOQc2vgmvqXU1HR7h/zVqKveMrRjVHMKTDApBB2eBssE3376KfQzsnQ==","shasum":"00f2db8e9e27f72ca35a6a2ebc0b4a87a63d2e2b","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.20.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgjZV3CRA9TVsSAnZWagAA4vUP/R/lzdT180xhdnurXKDG\nDzKfPToBH0Ohr6MuQQlRrwu4fZqO7ODAT3CQFcM787yjougjshY9HLBcla2p\nLzoxFqFiddslPiAldv3vXhyeceg9SNApVmQRWTR387SpHSe7Jyv1Wxg16Z4m\nIHG2H9MdvZPvfqFS+Du/r/XyuOCXK1q40zY89Al/zwl1Jrop0jk4mxtvZ/hk\n4BE73dTvsaw6uO4ZalSoVX5t3hCHyRvn9UOPlQ35uPXTJsoE6HRb7j160PbS\n7dxHt4lh2sPdlGiH+zOz5M1PyxC0CCkywyRHU7OuAsApBqBR8rCG6/TlMNnN\nk3NAvTcRJyCYJSKCWOjerdMYa9cDSSp7va+tH6Fuzn7jURTxwhmG0qGDr1oU\n9B8BrED2v8bN6VSVJnvieSkaPZHKD+678ToLMxPW7/9Lh3RpUgLS+GMVCMws\nhz3OhETzwepCyX2am/y2ZluqoLpE/SsyWPGfJ/BOlunVCzCZBfdhYFgaPSbd\nvp8mbP9eCMILAOreNWv4DPlmBwlZLaC+Hu5luhcHjRCuUIJZhfHTzLhOlGbo\ni41FQVq1uuHsWBKk2AznKsAFLvB06kw7pu3phx0R+QhJmGlNTsTSBsuJSita\nr0WaQ9C7y6mgP/XOofTra+3TZzmcw2IwxKMK8WQN673FvDc+AbEmIywXa/2d\nsKIC\r\n=mZyT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAG2JJGJEAYblrqhPTevbOU2bXKJe7GwxNP2gns1m12ZAiA7JvF9hXdnGJ4mBkExa643yzL/4k8OAUEBZ/L4iBhd8w=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.20_1619891575206_0.7920318388682415"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.21":{"name":"ipfs-grpc-server","version":"0.2.5-rc.21","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.24+21b70a1a","ipfs-grpc-protocol":"^0.2.1-rc.44+21b70a1a","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.21+21b70a1a","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"21b70a1ac38d53265daa52d8c0eef12d4e3255f8","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.21","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-LoxsEtwWVWZ43htdkFvuuTPTDGWQOtrGT260nm1p3+nOL+gd6eMJzDS0ur/kV+9H1o2gRAvxxS0e9eDPWNid6w==","shasum":"0af92b38401bde72eb3f7afc6395b580051cb169","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.21.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgjmo1CRA9TVsSAnZWagAAZjcQAIM/z3VXiilS8UN9bp9x\nem3Azb/XEa97eKBJG4HDQxr8C52kc61PlhNrEQtqldWsYdFKgDzROG7dWF7B\nbdGkVGG4D8wQgHzEB5vlRm8yAzEBCQ7eRPHTCpx/kk2sxoL8aFVDw+4CMcKa\nZDDgIS7bYCmVunOaFYOfs//kYw7XLYbzz6jnzBlPGAKfeqOjwu3fnFGUFVzB\nyGDEGL2qCJSo6vMOxrsii6O8dL/NBRG5PTIxj5jk1rpXUDFZOfj8BjExLIaY\nREZY662XZK9Hdkv+yJOwSWwlWYFEZNYbFUB+yqONFmfCbRDhuS3wBrPZ64+k\nuDBdAtueVU/AmHE31oBccY9/stgT0zovmOEqif65ZKDgcnSZ2o1qwdnC4hHl\n2sNJREqIR0l6x8x2mgdbD1TccGh9RYfaAGvZ5T1CVdLIVuP7wZCJ7Ln7RXHt\n1lO9OGqzrxPmKD0t48r4SqH6ucRgwCNJc6weaZ73ZLyztf2/+d4sB6Aosah5\n4qd6uqoh2KYDvGFU+l/ygGKCuLClkVicOd5TCFJHBh859Z5dKAT66y4lAeRk\nsyQnYELgrHSzNlZIzT8TkRC89uHksP6WALYoIjyuIAq1+ZVKyOTe0tonteUm\nDYGmZvMgH++Qoh+PJtugmklukcl3Hpk46H+9XMz+T1xQ5duFyAM6ty9XYD6n\nbExn\r\n=TqIr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD3n4KeR/DML9s4a8QS2hSG3WdDojV0OvlMJ2Vj7wr0ygIhAMqnAgaInFk30iecn04YBK8D+4kuFIu9w/52pCiH4Css"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.21_1619946036797_0.4670825852273095"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.22":{"name":"ipfs-grpc-server","version":"0.2.5-rc.22","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.25+0a4fbb4f","ipfs-grpc-protocol":"^0.2.1-rc.45+0a4fbb4f","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.22+0a4fbb4f","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"0a4fbb4fa20b17d80b75fc57be49fc8cd7c14877","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.22","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-yrZHf90l6Np1giZBblExz9B3CVYyhmkrMNwxYY3XC9xnCAXNzKH78bAWglTFyd9MPWrYuskn/P04XuP7U0ZWvw==","shasum":"397b5e24d0f6db16a72c54d24b419b4c06c99e66","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.22.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgkPuGCRA9TVsSAnZWagAA4NcP/i3jOd5GInEpA6LgjaSD\nO40+QtCkXPt8q7WnRa3TkgnvNTdLw/9RijS5wpQXTXJFu7uvcv9qIeGaSjdy\ncuis1gwUYxfbp2cZm7WxuHdABn+wRkAnrLRIm2dXVmKje4PMn2BHG7RyfkFo\nSTmx8XW4ADqS6LbTMKXQi+9YmFLQeyGEry25KUiGzRJlfBTktpvgHi6VoDG+\nnYFFJ4eLe7b2CgoCvkLoAUqJeQd3o/hja4xKsn0A00/eKha5rlryhOaGrvjz\nQrJt9VRug3c9ZPpUxrOoXk/c/hM7YZrElv2UKjSic5K266j9XPqxV7S4nlF5\nZIYkSeqEVj6LOK0EoZsCClc3SdZ/H1mgE5syaDRR/Z9sI9TNak7DRmAgjE2Y\nlFuKJQvbMjbQf9mlY/z+S3SkTQZJAq/eMeA7MNZ/pOv+6ZXwwZuleo1ugv4D\nnJU/2jhkFqFLstUsnDr1lOCScEMSQ50AOYrzDpK5W1n+XueNf/gbloqeEo51\ngLGvRchblZ4WWdyVUDbEbVH7pjDBh3AdiJUWudOmUjN92Td3ZgaQL16FEjDU\nCEaGAv1B8WLhVd+1eHrWi61QLkaNIixphEkXtHGACaerq6PhzqJt5nmaqZFi\nvFOh8f5wN03i0fGC8sNIcUhppdWPNnKOQwqIff/AeSQ9hGqhi6t/sqtc1ZVG\nyF/l\r\n=nNSO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCj7P3mDer4H4vw5hRgdGvpAvM7XzWn0V5Zp/fw+C/PhgIgRnzu8CSoIBscJXYh7ydkJEVqTpOyugo9el0g67U8OYI="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.22_1620114310235_0.9559861440865507"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.24":{"name":"ipfs-grpc-server","version":"0.2.5-rc.24","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.27+a297e8e4","ipfs-grpc-protocol":"^0.2.1-rc.47+a297e8e4","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.24+a297e8e4","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"a297e8e4770f0b8e88e065a604acd5928e561419","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.24","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-5+HFPY/O77Jfror3IiuwXLkDdnWQIorHbiQnlP7YgtlkIlh+XQEP2T65NKE6q6i1TpaLS1uK6D/j6uIShTTu0A==","shasum":"c5311d7c53882f0fb4283a727c47856db1aab08a","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.24.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgkSh6CRA9TVsSAnZWagAAckwP/idEE9Oco3BgcPZD6ang\nPWDJWsbRZnIaQ8679Sk8BL5rCdEStJjlEABlxzhrMeUmzN7BAoXFiEP5fkMM\nGbUd4KR7slQlZF8cS80DyGm7PTN0yv7OkdtGsyul9Pxun/01M/LFlQaWlaYD\nA3WAm7am6blvky+S0yKL168xDg4evphVyZYzVcQ2JtCV/Q/yfIirIDxndu/7\nUzydidf6cC3vwyhQ6qe02UbWARvOMpUWJ9zz9dEGzf2n3M+LdsnRZOOu9UoU\nVU6G+BnyQ/b+D0dKkhO8G/OE144ODQPCwXxonGqAp8DICRuwMuaYFarxXMZD\nQv5tyCY+kkfPdPD/CZr2n839OfkuDJ+VtWvXOMDwpmwUEx6I7actrofmVLye\nmEY12SGyokhkMDEfhwmgZgf1asBB9CJsZDR59dwsGzRsYjkXEo4o/jMbyInA\n7T/r+g8gMM/GhE5JUiq5dxH3FMMFRkKprL1hTpp91GkoRZ+L8v4ynK2WbfnA\na+/UppwU4PE6zzRTGj1yxzckgKIvKk1jtrcnVOdXrauJIkQTcN2hhV4+zrpj\nplWV87qn7WTsTeYmATEI4622mBuznd455sU/VCNi3w3+IjVMEqzGE309sKzN\ng7bHuWr5QmZ7Kv/zJ4lFzpflLfcF1SgQMPHtyAXskFhJrY4wcQCAMI/X9nx6\nF1OR\r\n=6VEz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB2AbXilmySniPX58DsaEJ9CztfLLlsEy06ACdOswOg2AiB1m0iGOJ+cp7zODJYK8LnpQBgEQhtKoYzWV+23SJVqDA=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.24_1620125818466_0.6241136283876814"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.25":{"name":"ipfs-grpc-server","version":"0.2.5-rc.25","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.28+09a65ff2","ipfs-grpc-protocol":"^0.2.1-rc.48+09a65ff2","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.25+09a65ff2","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"09a65ff238770978bc9a91449c9d76896f9db8ce","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.25","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-6sf5xzn5m3Z1xv1x8JKV9vPIvEnkEUY5kGuLhEocJfsRtqRkAEEjhjuhz4npei2L1htMULU6/tr1/2JebriFLw==","shasum":"3bb90daabce0da6d1604a06b16f2a010adbe65e3","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.25.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgkS21CRA9TVsSAnZWagAAhY8QAKIBgola5j2YC4zPApIU\nvgTK5ZJVkTjoZ4kvsXsxl56/zUL9H4LN6u95GoZpdKKGtVE/51McIc+9MWzL\nKFNmA9OedQ9WTCJMfbwNZ415rNlIvOxYMqdUrICr/KdqgcZeNfhpdewyHBlk\nUe0V/b7WiwIBh6gtaAg0/xBkzRD/WOUEpEXkevGkrorlKIIjZrNhTGwad023\nlxeKGebHtxErKCacDDEcbcQcz117M5LHKM5GAyR4pYl26Ol/NLh2Blo7OKUk\nctJM7tuUu14/Dh+4UhD7mfVujasAMMRThAuVKYCiTY0Cggf/QxMpA7+w15nN\nEHZUTdaH4NhuTxNG9htovMnjZP0OshIh70q3RlYVwghOFyAWEOxeYK80vqgh\nPxPPMPYImnrWXkk6qJmIVeP6LcYsPJ68eBhhVYXRvgpN6W83F8fcl5elBeYh\nFi7JjIhpMJ2Emzff3dxbD6Q5kmWNqDP5NZBKSibenZUcbWR98Hs32XcDyUe8\nVtqxuHxsAD8jBv2mrDNC/kpQ0E8PnGQpGPbJoxbQVQnMw5RI0bfN7f5YLOJS\nq3pp6GhuqHqwz12RYgv1mv7cTZrrGJuXTf8cSDk+ZgYaZQ+CY4HRWI8Eybtq\nEz2yNm7MXxBWpp3V4QVD+Ze5q0kRuPP7LKgUvIzjaFluyJuZKRDWIepB6rNd\nqAZE\r\n=1/W6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA9lOxky5s0p6Sd1w1XQlL1hQViPmwT040xCadVk7pMZAiB1mG0STlCs0rhWJRd9mHkIuuMW1mcf5C18o8B2M3OWPw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.25_1620127156925_0.7677220411520582"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.26":{"name":"ipfs-grpc-server","version":"0.2.5-rc.26","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.29+1173edeb","ipfs-grpc-protocol":"^0.2.1-rc.49+1173edeb","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.26+1173edeb","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"1173edeb04e6497a8e4d2336c83fa8c450fc9a24","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.26","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-Sp2AK5m8gqhk3pHhaD2uwNuxcnuJsJxacL2xJSY/sgz3SKWwwyI0eGitpy0I8ej+SrLbse2MTr56F0+PFz/c/g==","shasum":"a4eea96d7151ce2c1db504f9c38c5a3849b6be38","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.26.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgkVJnCRA9TVsSAnZWagAAJ0EQAJLuSRjW+ub6plg2oL2z\nEdQ0U3sZ/BF+pUDHS8V+DLMl+sDka+psSkA+FtOUey+wuPYzcNn+wO+e3Jz9\nkr5yyVPKM7pyVlWpQ3QDB0D8bSwivf07wXjSuoUdWPkqyRxcn9kJRuLtzHqS\nvaKGhk6pjmF+elyOEYqz5WpJ1CEPMciHiGUzYXF5lHSaaMv80UlLA3NzgHbo\n0CxnTb8OxirRTX1uJ2PeMEYBndHXfe1SINE05ZYy2d4FVP9z4Nt+YUOO1zGJ\nlXJPxfepdoMmE4EqT8NnufkkA0VzqEe/AFYMO6W0+w+ySsykmScj6AbFxHbn\ndA1amZ6JHvaHLjO+erZ8nPXuOn+Rl39PoFuftXcY/fK09ELrRV1b9WBycz/d\nzvbFOWYh1kU8DA+Ot67ZzTqKlKZcoEpPqfuf4eJHPReE6w0rmw3O3ntSinf0\nNyEzWIo9BuIKczzm8EBYfLE9hQ2ujX2JJ6heQgddNboOEhdgAtBd2YQf1WQZ\nvCRSMVRSoweTPIRIQr5Pi12c9cbUikDP5Ut33EMWdEmRydBhsYQY9jzCGISR\n/JnNg21kFMp3aQzsID/CEm/L5Lrj3eJ6yOV3kcJNl+Mxw5gTpTnSlkAvmpuA\nzS8z6wMNPxq7nZsk60uQQdOrcypwfWYJFe/qooh78AltjGjPtuj9mcItCmDX\nJktd\r\n=cxW9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICZDgmS581rNNldNAamRaI52993hg+31ud2CLIccmD6sAiEA9R+q2ynkt2mMNLYsVJEdijyp9ChmmUwYD6F0Mr47pbA="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.26_1620136551414_0.7551461163516417"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.27":{"name":"ipfs-grpc-server","version":"0.2.5-rc.27","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.30+3ff26938","ipfs-grpc-protocol":"^0.2.1-rc.50+3ff26938","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.27+3ff26938","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"3ff269385bcf0432e94aed545f74ab370d664557","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.27","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-e4dDEVFqgf8bNDCPZ7DywU0mFmcuAG07odhTdDseW0QdyN8WHVlvx9mabEJGzlCVl4UXTvzOPXkQjuC1ZGA/CA==","shasum":"8e625fa334d0f6401eba259fbb83d811bf8a6e60","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.27.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgk9ZICRA9TVsSAnZWagAA6lAQAKKpJVIhlDGuRK6OZztg\ns9PrXskCqljRWp0xeg+0yRKqGBxi9wV3vyaaSzuJ4cQ78BLI2DobCHxC3SoA\nzgqRhHijPili/iN1au7P0pOmKroAT3x1ZaPIwjzelsdNKGNdm2ALesOAx6Wu\nGI47McmaWB/psA+FsqBO3Elphv+z/yh3xug2eU3aOVWlF7C1NjJiL91x1DnW\n8EQ1TWxWiZv4br1QRuJKfIB35KF5D+m1B1DNDRJLX8mAx3ql5CDf6EgY7Iyf\ndQBF0aSM2VTN48VOj20vsZ/dMOg7wmWAhw/qyZCaRtKl14EeyVv9AyvJY11c\nqK/I1iMZ2Upbd7MfTZgtSyKC501yzrtp5wu8muO0ed/LiDzRW3tms/A/UQR6\nthiv+pME1bn4lZ6y1nCReApZFDkhwWnRwaB4tJSDj/GFLtg3KQHvKED3JbVq\nBD2vIzVZdktP004a17OtzQzeHIAOtaj1lnLTFARRBKZzcLilBQ6d+PKMpF40\nhsN0IXwoGHF1G2KfpaaRIiqPnguM4OttYPNfAD/xIVF5Qpk1XUsrPgph31pU\nugooZEKFGmhqdL/dp1Gl6oXe5JOAY0zmoNwpyAWhq5IfMIOeQUZbPtAUon36\nkBRLFP4TZaZ0xZmb06YuUKXPLpvjZDMSOZynfP0IMl3qIIwSBl3aZeB8KvEF\nlxbd\r\n=2Adh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDYJ+XlOtuDScOc4KHDW8X54HASlAmvoQTGVpcUGJ/ZNAIhAIPTTqWlAp0f/4bTViW1eMl1zsET+ix0Xv9kh9WUUFYb"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.27_1620301384016_0.5545926668843539"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.28":{"name":"ipfs-grpc-server","version":"0.2.5-rc.28","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.31+d5897854","ipfs-grpc-protocol":"^0.2.1-rc.51+d5897854","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.28+d5897854","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"d5897854419e83a146dc8cc01de04e73b250d07f","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.28","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-LRQgUCjlkkOmETn1Wwr0wuQpbFfmkmxcauOlQCnYFQOqugAesaB1k6LN8vp38xPLV0XyIk2ZRSRUlg7KSmcW3g==","shasum":"161ca6dee91d8a11bbbd8a17c2f253fe9b2c5ad7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.28.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgk/qWCRA9TVsSAnZWagAA1EIP/2SJjopNFhryc8WYUw24\nn4SqW7hSNZOm9/5IAubyrq8ZtWjxDDMiC4SMTSJMycUqweU3WxInIU2bukxG\nRVBB8aGx4WyHX0pAZHvDTB57it9B8kiU90zack07Gj8yW3xo+KgEXgXAdI9v\ntIe52jmBcWNbpqkjafQk6qlSogGdtjLI3RVJNE/SGDwNQUOgvnOOBWIe+rGE\nhOaf9QFgPkxOoTcfjYnCxykxYPBILbKoDnpKtVQHOqaiLQgDIUBidGvma6x4\n3tmJDw+YAKqedWMUwFdI8W8396d6kPz1xIHwRg22Q7HKTZ3dmyxOKUf81YGt\nDjNIZ9C/C3J63il9IGTqDiAQZ67Djd+2KyTkYUeY14tfGFUxntfUjZfdm+Wm\n+m0etRAWR4HBDRCJGM1eb44ZLMinRVklyOxwq+hWamK4xbLRsejXpK1NnN0N\nQnAF4J5s3kISC3lJmxnz5DCJ7f3+McKqn+LsVigLvuGuOA46imnE3hjlN98/\nM6Ur9fmHJv1U/LvhM8TnYCz4zSg1AFRKym9Tna3J7JKoqvS59BPSRHzW4G6c\nlFrEDgQHEvRfiLG3uFEnRQTDVrSwpVb9Hf47P7pvJ+SK2zIsSZynXAXkj1jF\nvdkKBcx48ioIUX8dUhJSNQyAjtlDKnI6V7TywxH+HTZPU97HUjHIGMAqL6mV\nBecN\r\n=Fu6Q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHQ4VRjufkNaTk/LlPx/vaQNx0LWde8pzerHiC2q/I7dAiAPTFgU3k6Sf3lwEIhmGTo7n47SwrdcGaUNXCUuVH1n2A=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.28_1620310677744_0.5014319571958867"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.29":{"name":"ipfs-grpc-server","version":"0.2.5-rc.29","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.32+3923133d","ipfs-grpc-protocol":"^0.2.1-rc.52+3923133d","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.29+3923133d","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"3923133de800ffd5a5550da86b7bca254206104e","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.29","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-jiH7iJ9RdgOn3HlIBCUNff4WhnxHph2XpxfT1dDOvlYj86xGx08QvXhP+FOd9ZZuuvEQ7GwztMi8djKOM0JOgw==","shasum":"2c8048134ac36b481785fb794df430097f564453","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.29.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJglSuTCRA9TVsSAnZWagAAzrgP/RdC/LXfjQADELD3+pms\nT+j1xyX8NUgVDuhQH5GdHTV+P1SX31yTDCQicaDf8vF3jxO5QqlCiIQKIKBr\nutI6nWZfXSai2fpEMEaqlltguEnVg8cLOJozHjY77Fh6wPzMo5G3x0LrcZPo\n/y26udpddTU+I+zETeDBXg2Wqbfikr3z1SIiklbdRKRU1204Jddcn/jdYPsl\nqoZcwU5xtEItPa7wBbPr5AiUEBQwLmFSWUtIwVsLYr21L8urnlFEvNXpUhmx\nPt6/C19uHytHLh4/jD1u+o09GNuFIpHKl/I7X+x1DbFz3UaINXu77s2iHTC2\nLCZaZ7T6n3j7jG3DivgxEcqYomoCkDi6IRFV7vo3GRRsNM/WbYqzm+05zuE3\nwXZ8riCT37vJr93IxfGAv/taqF8lLTYfOj4/6A68CSm3KOkaJGR75gKzuCPu\nYgYy90E1nXZeWsWXhPfQeVP6Xu3WdifjgAv/S8YWPR5Dxx1NxcjKw1mzWxbd\nyuW0nuU+9cBF0NwfssND4XDxKjiCAxxGYUJwBwvd0XV0mdxhEGOmqbRawIr1\ngwnCzHXQnmocBzCAVOGEc2WzFvjt2bbq9cSMJsPNy3MO4McH2ym5JkVwcveO\n2H+BwWBRchE8lcHj24+DpDZGVps4zIK9FvVoJlDX0mUoAu8F2TVvsEIWlwNC\nFsTM\r\n=MsqC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDDiykhij4jkxddOlkLmlIjmwgpZOrEEoggR3z8IT4ZMgIgV9cZcwzeC+Y31mmrJljk9J9DtyIAF7ki3sAOrolvUiw="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.29_1620388754764_0.4377699019525403"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.30":{"name":"ipfs-grpc-server","version":"0.2.5-rc.30","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.33+cf78a190","ipfs-grpc-protocol":"^0.2.1-rc.53+cf78a190","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.30+cf78a190","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"cf78a1900dca2d466b3694dcf677eabba5ea3b17","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.30","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-PVk/5k5gGj455XYCPFXo+vYU8JVBQgjkSPKJJB4WHCrzGfcnMsgFCEYSBg8Gkpv9LYIOMULvEGstGPSKOvoF4A==","shasum":"508a04779668ff5b7bd6054e9804a33886b91ef3","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.30.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJglUMjCRA9TVsSAnZWagAAsG0P/39FlktLCteqKKiGvVK+\nT3cGnRJR98CIdQuFcVy6+smnAIfGAoxZWMw/TJwp9HTZANigxSI+G76hX3it\njdf/YCFZwy44mJINMgfvYi0RpYU+zPk6NBBALiskyr4GYqc9mdcw3VboRdGe\nOGJV5Nt/uA9TB+OSKvg1e0lZUdG4fx8Yotn/gFxhVfz6WSqfFcboOAtwYtNV\nzcOnNMzLVYo1+a4mrWBzeEd28HOOXUTKi7kjET0bPNCprxVNpZdE+0QcSR9c\nR/77T6cuYI5zOwSZ9yoj/dIPSQTDPmeQEmoT7rN52O755zrQ4rf1jEKVagZZ\nZWQh246Cm2G5Vp5WfMf1i33P0kgbKq53TAVBKLsIIbVunftOPHPRgmGdtTfn\n+mycFmc4dLLRdTi6cltmCGN6Nt8J9MbSInmJgNT/zAeLN7kIp1jVPeXnbndi\nbaaHZ21WiatQYPlJYHOAmvr6KgbTATx/INruM2YqynzqNqtGUcFf1ZQs4yGl\n19+Lhp/gNcR7qcp6YewpJK4dpDesBhCyFnSu/un0BFmITYYUej3rvRd1LiPt\nPRcdBGE9xBiO5b+8Y1tjJMCcOoxV4yI79ehKEz2J8ZfdxjLljddCKZLVeEj8\nbRIEyYRkkI29d30Esit/+R3IK4etBu/L1tBYM0scQY6vSHHWoObVk+Lm5dHG\nhjhk\r\n=vm1T\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGEihDGeYD9p6EyDungBJo6QWOC5IRsZ/3fl9wSb+iShAiAdzVaubZUJuXvBv4lPLcij3sPNRqlKa5EtrrQU8nNW7Q=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.30_1620394787234_0.4914114751243708"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5":{"name":"ipfs-grpc-server","version":"0.2.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","browser":{},"typesVersions":{"*":{"*":["dist/*","dist/*/index"]}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-grpc-protocol":"^0.2.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"aegir":"^31.0.0","ipfs-core":"^0.5.4","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^9.0.3","uint8arrays":"^2.1.3"},"gitHead":"f7e44c203c2aba94548cfd32c58e5510fd3d5557","_id":"ipfs-grpc-server@0.2.5","_nodeVersion":"14.16.0","_npmVersion":"lerna/3.22.1/node@v14.16.0+x64 (darwin)","dist":{"integrity":"sha512-mAGRI4n7hKpBb3kwFpi9Bn2elLJFA2vzNuAlKCn9o4JTlhiCIa1ocCqNvTaN7nGcEvDeFmA1YgPVVUA0Ot17Lw==","shasum":"2e202227444c8bd88e33950a4ee8a428940e2663","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5.tgz","fileCount":31,"unpackedSize":211332,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJglWCgCRA9TVsSAnZWagAAHDMQAJVFOj6zGA+Um4GAdqIL\nIi7zV/7c6LRtG5XSEXM48bPkJnhhciiw9beOWW+BB9AL5oxmSx0Cqc5XTL4L\n9acSiNfMC6jeKm5ZXrFjNUFxUXomzQSqum4CiTMAt2jRyyymKQXV6Jc+XWzv\n0M8iVHsShE41zlLKcydkBGW9iKE+RIj45WfK21u4VyLNMIB+F2gwbpyZ++bl\n69aHi++Uc/j8TywnSpzIl94/+/QASgahHZ+eC+pNaOghQQfevCG/QauLkdH2\nxuue51wZ/66bM2OqKHnMPd2q+SuI6N2mnqIhtinE9xzEzsVLDPG/AaygVhSS\nskxmapGw5PYjOEdY6D06yRTjmXgnBAn7sKM8cnLsDZ6E3BLke510vdPcCep7\n/H2lmzuHxoJEAkJjE4ilt9VnPpPJUs/d4It+DRAlOSbK49DyCAp9RaFtzxFh\n3UviPr7/Z/IMWNnFlRDRupZZKlmCQT0TwuJO5sX5fmAxNr6MbpLiaJrdGTGT\nodAYyJSETaJHhLh48UzxL5WzC4CC+OuHhI1qn2UVj+jEj+1U51h7ko5uMvLq\nKcvZ48RafHMOHoJmRXEesgkW5nGjTCCUSXcv+gJSIv+rSGXeUsmYIPqalzvc\nrfswfBTYcUuPFZCzthsxPn9eN/PLHfWQQESc3wY1vekKndws7rwEIgNqHjZz\n8Dx9\r\n=HHLj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC7k5UrjmVptAy2F/7dkmpVOw2r2ha094zegkaY2IIbzAiBeBg6Mnkl/+P/dKm5WoZce3L/rOcD6/bXkrf4WG0yXXg=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5_1620402335722_0.6118930483129947"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.31":{"name":"ipfs-grpc-server","version":"0.2.5-rc.31","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.34+fe6024ce","ipfs-grpc-protocol":"^0.2.1-rc.54+fe6024ce","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.31+fe6024ce","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"fe6024ce70fe83da84bfd938d725f3e6814d0e9d","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.31","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-TS/6qoKvvEbvSkP6BDe1wdtlLsNfq/6bFMzGxYvInt/Hpu7bhTg/2xZ4BRHDDhoUpppIRd/9sEmz3kNz4EyYDw==","shasum":"84c9712e42e8adb8b3458e1d12cd6bc74b54ee33","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.31.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmR+7CRA9TVsSAnZWagAAf6sP/jKofxqXitp1RvtD6XPX\nvo3aNV+XQwMUSlZ6SjWbLQtVpqJeSnJVCDdwig0NcXlkhkbNMBNH0zP+dP6S\nABrEk16aTci+QsyPFE8BgzQ+cV4gAGbq3wLSxw2WJ7RYLGqiWjtzWU1ZM6N4\nX+6AujfGzJG4DByDWUbGBxX2znupeNlUStajC8+b9PzxC0P1z38Th2lDPmcn\ndTltkLqu1tRZ4fz7SR64r0macqJYM61AYXjCEfPmKVo8WiLtoROqunAvcJ49\nElMjm6olHTrRD9M9bUzb8ws9BDMxQRhAaHomThsxQQSoDNXxDnGm2Xsn8Zyo\n/4BFvQOIWaL1mlOkcqArXg3HsFEsugcNLggXF3TVTHthSXIegFCllTkAvAtm\nCV+4uag0wk3cQkJehluFTWL4s5csDUgieTb1DKZYVY86KxXJlakX3mTUYsk1\nDZ3eS71XZV5BWzFXDZH8dcGkvHfSE+EKeuHJ6jYzMM3AOEx8Jz9LNfeZb4mC\nK9gO9pA53QhwZ/mXxj71NS6VWaC9HrYSreS7Ua2FFlCcH71qO4yKo0any0Bx\nLCIAer9aEERvyl9628m0AyjkwiShPFzUnGf5c6aA8yy54vQdmzKXMx2by0XO\n0S1lOoq5qy2fj3dWILTvNRIl4foN5WfRqcDEOWB+LycBqhA2DOkUxez0anpD\n6DUI\r\n=1P3W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBSVsONql12aDUCtYKxPVJxvZxIaa8bcO1TcgH/okdTgAiEAyG3yaqoyHiT/qfVzBJfk8xXMj4nRqCcj0JG5QEaxRtM="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.31_1620647866725_0.07330216632848385"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.2.5-rc.32":{"name":"ipfs-grpc-server","version":"0.2.5-rc.32","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.3.2-rc.35+bda04d10","ipfs-grpc-protocol":"^0.2.1-rc.55+bda04d10","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.5.5-rc.32+bda04d10","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"bda04d105587606ab2d7efba04b232bc89b1edc3","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.2.5-rc.32","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-cymNmwzpMd+5WunitD8s4q1HDbmuCZDr+T2ESg3zIbn0uEYvdtAGU+vkDHGNZ5O/cUZwmrYslmlunfEnfAzY3w==","shasum":"8729adab53af6e284387282d817bf4cdebab4c95","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.2.5-rc.32.tgz","fileCount":31,"unpackedSize":35410,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmSU3CRA9TVsSAnZWagAAQSwQAJgpsP/EVPEx+x8EpxZY\nPaOKCaYqWy/ImXnEdQ7Z7fiLCfElTVuFCcP1OCIrjhRCc3ZRZpEuXvv8AwEF\nnuyk0hOD5d1Qicg00Zol7DjPBIvHZz96QY2ga+Z0Kl1IpXq6AZ907TU0pNia\n49ULm2M0ulCreVoUbCnwfD5axdMSJRzAd7v+dBxaORuIem0dwoJIPkQU/nPv\ntJPl2fiV2ipstyb/MBnab2vfuv2vY5wDQxLIIRLxKSO7bCjvLj0VPe2H/Kij\nuFyZIBka1sut4B4oNHZDoXttCW4Rg5mMhEB00a2sPTtZkIdOpktE+72tTcq9\ndrk+rfh8gzIcuvqeA/SHqGN79t7mJ2jHI2rjup5GJAu46C3UplkBR71reTVS\nVr+Q6hjKGWoqX0YAXu8cycY6qEiBAyyasvdIUe3LgQYjcKnOMIUzLQMoTlEh\nMJe20YrmRqkpKUdRKEVsK8qjCgmmJ7ldwX0/l0QA9XM563lXzmraROs49MCC\nD9Lznp6Z39nGp0artAHw3Eg04WtE2f9Ir0KQ1fr3SZpREnNSdwl7wMeEkJW8\nhklzAjHBkNpMhB3q0y7W1Pti/fwwObuiQutFtJM6ldknqZb3hsQE8VQjO3YY\n10Gc5RPSTRi42uEZQnPQaXQeRYYUNRRWRmJju0wwcsIpCdAw9nynNVTyO637\n7QIt\r\n=JhiW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDnfoV6ykDBKnTrs7S6IAGJvWRL4eGsYf2fwj6p3KMLAAiAetIQcI1Ryuz1yOlrHz02Zh6ItrgtdtFVYXAZW/HKSSA=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.2.5-rc.32_1620649270646_0.5077623572977941"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.0":{"name":"ipfs-grpc-server","version":"0.3.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.4.0","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.6.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"99053f721305d1905f36a16631f036e883cb02d0","_id":"ipfs-grpc-server@0.3.0","_nodeVersion":"14.16.0","_npmVersion":"lerna/3.22.1/node@v14.16.0+x64 (darwin)","dist":{"integrity":"sha512-XvphaZ5rYDASqCWgnodW+JNGXENtI8Wmr7AZ950hlfdAYLJx4k5FRn/+BjFpmaXew5cLRbjOmh/HEyZADof5Yw==","shasum":"790a999c42fdbdae8f26af4d382c4a8fed4e42a7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.0.tgz","fileCount":31,"unpackedSize":36257,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmUjGCRA9TVsSAnZWagAAmjIP/2fVbKZtP8Ngpa1gUwos\nQBTrwwD20c1g85UM4Vj/8DttaBm8ePMf1MXdMRO+Oi0QomVUAWiV+lYWlNEh\nthcM9tNxRl0U/xQtAXhK5Gp1w7uzbNmZU63bpho6Pma2xU/VrrwUDzO+L4UC\nvztt008cO87L0i/XE0ZaEANV/QMWjBUovqNBnKUxJ8KPPS9RrZovOHXtubs3\nJ4WaSsA1E+N8FocnSz4IafekL+ItEP9+CxpzYuiw8zwuR55b/BFBij+z1Hy+\nC59xYxK+rCcwzGZt54nLiNqGFOAA6UVtTA0A7iU7BLC1wJdJrNcYe7422TIj\ntQDFvsJqKVqWQTCkPHnmvWA/hYu8MlCY/GXadky2d6aoiu3kNC7vSDANzfQ7\nHl00UtKKOrFvTbWxvPQHrhyKfJqFLY52sqnBUzSg/RVSUudL0SuKh4MWm7kY\nTG3YhzWanuRCpTWkf7E5X3rE2v5nSZok+VZyJpWkHRUBYsyW0Mk8tBUdlgYZ\nvoeyymVoXNHYK0y2rtLr8W0uNCXQihf1xintNi0buh5klgjOk1s1q01dBvRa\nmlbuvzelhq/B/8UWVyhcMxipDOR2MZp6Uqtf2rVOKMyGuFOZ6JB4xpmtJZI4\n2M/X/RT+LlLA+SBIEL5XiLsAtP5O1TLTiWPjd5xH+ccaqyjo/NqBNwJxZumJ\nbhBb\r\n=Ryqw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/hhcRZfXPjO0zSFC322YJ57yQGWCXdZ+pjfG6TwVFvwIgGT/5MLfcdCBTeBiMZr4NYI+Fci9i46SwZdDVOrLXnPw="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.0_1620658374061_0.19039107711135217"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.1-rc.1":{"name":"ipfs-grpc-server","version":"0.3.1-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.4.1-rc.1+7f6faa76","ipfs-grpc-protocol":"^0.3.1-rc.1+7f6faa76","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.6.1-rc.1+7f6faa76","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"7f6faa76a8b1903242f941837e2c717cd8095d10","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.1-rc.1","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-YPcoHkPldipsVbkQh5yuWgfAAeTOFw3S9V5xpNbyGEvqYZHrAQ5mFu3ubzyBLg5tpp3ERrW852pXRDEbWF8EZw==","shasum":"81f9a20e5196557efab5d309a32421eedf81e876","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.1-rc.1.tgz","fileCount":31,"unpackedSize":36313,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmh+rCRA9TVsSAnZWagAAxccP/iTbbILyIB+iINZd9APD\ndS1KRBAYkWCb843eidLM4UACOv/Iy3q9X+EC65EAG6PAfIKrhV5nSw89mmW1\nt58VGLwrXt7OagmEGjcBUzzn2aBcKQTCO6Rs26i3O6QW3nQ1WteIiUh97v7p\nPslcxaYHRUr97LabiCbJJQpgumaTe6b1P3vXE9NT3jVp8X4/LvIL1nXaZSoX\nVdDE4wJp7qUKTtE0j0T4XV/m72LStKDdHXVCSullcCENq4Env86ublYxRI1S\n6jDZwdrGMR8Dgr9mW8p7VIU0FrxR7EqnspyOE5L0r62/d9BP4opb/9SCDrj2\nCcJdEbw7CtmnoYA4ZDnrbJoFRcIMWvGdndQ6ElLrGOn5Y9jQlf9JpOTPTaYJ\nwuCgcCx7GeVh2GDFmLhd1ZFligneuMYD8OPCgQRMz3utjFtybsDQ1Rs5SqNu\nkhvLNryQn4sdGcIozRCYFKl6pEegwyRbIyMeZMyaP1EAVhvW8LWgnJLxRwTk\nvU8qaiok9V84vmJO0UQtVHsCpw55QALKlhpIELojW1KYGV6JW6W9XTcMYPSB\nnp2jPAmTSMk34LSfMtYd+Iqxk9VYCT6cYCrIsRpaI9OXJ+PjLp10hCVts4gU\nFdLUhxgWyrjl8rW2ifgL9pBYFHUkSAKwdXtHNLv9zRhGXgTD6svsodPH/+oQ\nSsfk\r\n=698H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICf/cDBC/w8+HXqg0EWGmuMIc+PnT62GhxEUPGN87HIFAiEAsUacEpbbVj+hWZU6FVOq1Ly1QPowehTU4bkn7Rg1rRY="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.1-rc.1_1620713387331_0.44006010656575767"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.1":{"name":"ipfs-grpc-server","version":"0.3.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.4.0","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.6.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"bdea5bc95073f568a3b0ff75ec5c26a64dd2bee0","_id":"ipfs-grpc-server@0.3.1","_nodeVersion":"14.16.0","_npmVersion":"lerna/3.22.1/node@v14.16.0+x64 (darwin)","dist":{"integrity":"sha512-Ljb0L1BSEmLJRLjY0Aes93KMKfnK52U1GEDuriI/5KkWS/AUC80h5+bxJGfr38pfj7OBRpMPjMmYqHmwgUFyIQ==","shasum":"4a7f513f821a21a0130b88f9bb35297f7208897d","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.1.tgz","fileCount":31,"unpackedSize":36433,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmstTCRA9TVsSAnZWagAADRQP/A960/n5p0yVVEZbeERk\ni83tSk/vBcx4bw33Ssx8qxsCFssrd7ykj+ipOfvzJQsDaM1bjGqNeSHDvZx7\nFVDFPx75wjpoxR2Z8cAMRU0MT5gWOAyN0HvZf5ytT5SpTJlhsWMnUTiByCP/\nvXh2c9jAyCTKlUDyrl0xGlQlahWjSzSUNVKpNUb9I3gB7S/h+OyKmNO922hG\niQ/BCD3zYNu124SJDZVK2dPxEWEldXRL2YSqCTMj8YiUS7eKPcwd1nTHZdHl\nzdKJ87tzTPfPrAMPO8fqCCi6q6m/dzWrgzpsPddxKSx+p341st6n/kWSCpoc\n/hfwA+YpRV01TZc846m0Y/fPgFMbaujyzpZcAy41+UJJqQsCzYWMxWGqrzUr\ntwJ0s9vODrSUHG/htgN/1d+cZzX3RdshpRH+VNj32GpZs2VIN5yYV6wpjhmf\nAOTfTHR1R6Tx38FQXqB5DyTBZqxNXicj8x+k7uFV8vDQLrwxNVB/aoahbj36\nz7lowafpb1c1g6jbqWUBu9IsVRuVWs0ID6S/gR8zEpeOMJRLr833HanTZVBf\nKzVQdttQ94Xwq2WEQdn6PGh8yncSAYYvFMkVwaXRqIZc7q44/hTmpJJqmqwL\nw283j5AuAQuJoVtpYGAZCX2vrUQXrVmiVbdbLKGg0xrWzlcEKSZi+bXnqDSx\nJJGF\r\n=hfph\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA1uSTryWqEN7pvQWjR7kGIcNUKQRpeKiAnkAMarmKvqAiALDtinoRsBBej8Z6n8GywmkD3CzESfIs0E8FNT9xk6EQ=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.1_1620757330461_0.38534974088686336"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.2-rc.1":{"name":"ipfs-grpc-server","version":"0.3.2-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.4.1-rc.5+18faefe8","ipfs-grpc-protocol":"^0.3.1-rc.5+18faefe8","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.6.2-rc.1+18faefe8","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"18faefe8bd4ee1f671919672917b848436247138","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.2-rc.1","_nodeVersion":"14.16.1","_npmVersion":"lerna/3.22.1/node@v14.16.1+x64 (linux)","dist":{"integrity":"sha512-TfE0nSoiKtAnAFZ+h8UbkfcLktAT87ONN8wDaYBYJyBi6iADdjUHAzY4o+v+XDTe5I5CBvumRllMNK3ODnf+8w==","shasum":"e27285b4691499e948ead49ba30874df77940fa5","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.2-rc.1.tgz","fileCount":31,"unpackedSize":36489,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgmuiqCRA9TVsSAnZWagAAvtYP/Rtegq9nfrMzzi/jAhjM\n4UY/ykWdHvzN+wYqK5744mTv/pqn0pt+8gOrhoVIE2LPaAxTaT35q3YOxc2O\n8M1RiY2xd0U9DYiHWakon0dn4zGTf+968pAlOxfvIVvEhRLEr/5G3k4z3bat\n39aVq8+wXrXKUt5xNsAVhewWPKRz17bHS0ieaE+W4iN0zaODeYMWPJ77CGAV\ndc7Qq4HSTviSPAfPPgizjMUttaUjFJOTxfqZ4QSsTO2gvrCJKjklDzt0nfde\nDDbfX3eJqYFglgYQO1TXkfgjCzWeJc/fwJScUYBNrV6nP3wP6myFvDvLQIWz\nl/MMaoQ3GR1Zl2Kd86t8S2XO32y06+P2h2SbgLguTOWkztZY5vrT0wh9UJ8S\nP0hVrLr3IcjsRt9UZ3ZHbGuZoSgqxLD5eY48qPOZwv8KlIsQ7xPjL/GLoFNx\nOeL0L2uvsea8f8XM6XyhiPAO6Pj20WBbcmZgfkMQrJBTzg8qOmyMRe++KAN8\n+jmfx7AXL8K5FD9P37vxnOfo3NMLSPVxh6emDHNAmAijKlgDAGfpaaS/eN31\nWsdLlYrMit9ofI8gxwVrB0ImAevv5D+bXJejpwkNyla4edD5GGv1Zc2dKVmy\nTyMMljQaXzIjOfTVWJop1DQ6A8Dp5EtwUKYWgi17cQjdfW8n0BYHssFjO65R\nIkMX\r\n=8knb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAMh4kryrArNjw9eXe9ZtxOJjeGblTuUGnbNOmZzYaHPAiBZQdJFReDWacCCMGLYd58u1LmO1/g0B8TlbWCo38HaQw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.2-rc.1_1620764842097_0.2183000202065033"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.2-rc.2":{"name":"ipfs-grpc-server","version":"0.3.2-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.4.1-rc.6+311ff504","ipfs-grpc-protocol":"^0.3.1-rc.6+311ff504","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.6.2-rc.2+311ff504","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"311ff504a98ca562e738eb3bb60fddbdcb5eebf2","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.2-rc.2","_nodeVersion":"14.17.0","_npmVersion":"lerna/3.22.1/node@v14.17.0+x64 (linux)","dist":{"integrity":"sha512-X84XpxEWnXPpWHsIDeZNhdlXXrndvcAb8eoK5ppOqhtoC9UhFS2WkCTNv8/KJLVG95LdLnIwIOqfDY5NAGSLQg==","shasum":"c6fdfae5d1f348b45ea0029a3eb1c50eebc83ee8","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.2-rc.2.tgz","fileCount":31,"unpackedSize":36489,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgnWq9CRA9TVsSAnZWagAAesoP/RYUWpwYqGsWBt6t1dSD\nV0LfeEb+pemf6PywwSqM2GbiQOL7DagjYreT7ObBBK5SqKXXfckfea6iPV1X\nE59BBHrkZIMrgK7PDLuknrG8Lw02jk9q9iIT72N131Tqm3OHih94snDgwu62\nt2N46aWxK9KBYVX3qQ4nIZAxAuGt29UkjsTktU4W+3OmcNlU+jXepo+Nmjg7\ntQMjvkLicJoexJJcYe7C3Oays6ktWMEyOBeIg+R2WamjF9d5aiN1Hq7Z1IMj\noMhxLhzHM+XaTcT8wtro8uQmKT8I0LKFl+n7334OKGmDUOBMtLdUD+KyGRfR\nfA3L1p4QBSbMo3yYszNprXq+zmqSIdK6sT5/b2yB8KM5G4sDnqvI6b7+tuTr\nCWSC/3ex4Qo6YSlnzoDlat2QQL4G+r6SxeVeVfvEUhn4MbG64fqYI3VzbXNT\nIaZfpIsXenuvMWM/lnbFXogRYePRZ9XC2pCBmG4clsKetMyPd6KTvb9Z3Lq4\n/me8aZeTikDFZ35t7b1zryE713KoGOdIV3v68Te0U8gs32ZDF4hcpvMPUGV3\nDpUwP74W+3rik57eXry7uTPfEvRnOrHHrTRpye6/HNUI1IC8R+8O5lx7HOTy\nSuqJRhcoNBssfSA5U3mPtAQkKa8tSqOESSBMR7seXMlcInAgu1EOoIxNOUuh\nJU8l\r\n=YfxR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICmCUE8GiAhHQsb9wWTYMjjCl+Mx3uLVf4d08Kt6PT1PAiEAmvBR7b5dwDhdouCxOcUeNPcKrBCWSknaY3rMbM1QOTc="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.2-rc.2_1620929213276_0.9995164212552157"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.2-rc.3":{"name":"ipfs-grpc-server","version":"0.3.2-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.4.1-rc.7+1926f990","ipfs-grpc-protocol":"^0.3.1-rc.7+1926f990","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.6.2-rc.3+1926f990","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"1926f9906bcff5bdc8d417a7212a9db52ace7e3a","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.2-rc.3","_nodeVersion":"14.17.0","_npmVersion":"lerna/3.22.1/node@v14.17.0+x64 (linux)","dist":{"integrity":"sha512-7ddf8cM7aaEWhYsXb00j5v8juSKzCg3WaTR9SewGO3wVINk9l7g3NuSvuxXS/mA4Uqe7LNm5hfjGKD4TyDtzEw==","shasum":"6f481d6103beb130e5a0bc9d5f4e22237524854b","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.2-rc.3.tgz","fileCount":31,"unpackedSize":36489,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgrQxWCRA9TVsSAnZWagAAZSYP/iXUlPpUpQ78HToZdOcq\nFQBwMr9joTmkBHn4sW64ZjswXUTw7oUDuGJrMh570mLg3WFPzt4byNezMbKc\nU7LlKtizSm7SWLbwe3dcKZycr1vMkbpqS5RV3XU3i1LdBdRc7fL1k5DzmdIN\n0jhrDkSU8TDbhC9mArkaFwFVcWgKOAptEqrvNHZx3k5f9lqH0cCDOKfX9mKJ\n63OmxctBzavw2Hq+4i0jo87S02E6b+Yh33geWPj2D1Qr6Dl3jId65MXB0Lkt\nyYQlSsSrQXBxIkZ3KXvHicRj9vdR+N9p+5TRUQTamc2IWcfcAgt6pJUSOOlx\n/24QjnBrlYKrkS5fl81LcHETRrkn1P0mdl5YLv+ivnvlpPkT8w1gsPDlfSRe\nTeN99yLRa133Y9P+e8z1U4NCZLH1idxkGeeNZuqzg8cQK1DgbnadwMNc83rX\nN+dJY618ymt8HZR/lxMomOQJ6fpkbKhPMzrZ62wxmyRnW5Wdd5maqHLhjB6V\nkLPuwj+SGRZ8mgQqXAEQycizTo92tPPGkjbgjZ3J1pj+boz2zkWfNbojC0ei\n+gFjigkMICJYMYnKfgAbSD5Hb3VpADqeQS5qNEkQQ+mVeVHapSuAuq6ggvI5\n2+iUyrEyKrSPQhBFdEJKJvMvy7vTEjod3H1deiEZVjX8PkpT3YtL8MeAp6rE\ngvC6\r\n=T43Y\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKdgfwb6Q0NkKOUjbqBVS0GbHBHCfzaIskaO9BJ15vDAIgJ8JZBpjE1SXsPWqjDBqhy2hsGwQLFylY9gaETdDKV6w="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.2-rc.3_1621953621714_0.4047643939078762"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.2-rc.7":{"name":"ipfs-grpc-server","version":"0.3.2-rc.7","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.4.1-rc.11+e91a1e52","ipfs-grpc-protocol":"^0.3.1-rc.11+e91a1e52","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.6.2-rc.7+e91a1e52","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"e91a1e52b86fcc9ce5ca5881e8721863b58d5d9b","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.2-rc.7","_nodeVersion":"14.17.0","_npmVersion":"lerna/3.22.1/node@v14.17.0+x64 (linux)","dist":{"integrity":"sha512-KIjWiv/2vYPpWVb4UsGYErNC/gDCl9OqdcMntPnNIbbltz4FNDOt7VRE9WvYWA66tpZKXUeiNhqfhT3oBmuxhA==","shasum":"3e206b4e134019ce09100c0c444b4c6e75cae02a","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.2-rc.7.tgz","fileCount":31,"unpackedSize":36491,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgrSCDCRA9TVsSAnZWagAA70EQAIB1jG5giWfZAX6Aw7XE\neqS53AxMaZa+UK0DY+ZqugSV1VfpNIfUci0tvxtRMlz65AiV4C8Qpv+tNMxq\nxjawhgtXb6sb5drhOy5+JSNNB2Ds533e78MHzQ4U2Ed6l/cqNI4zcR3Bg2DV\nRjREdIkadnUQTA20v5Rqj3/oY06JONr6N3CsJzxnpwMhzxKLiPdAe+pFJyCw\ngvqTlt3+ID8UXV7wRx67NKU4/6oZh/w+AIemgFT11pP2SjdsVmNOLcRxbfQM\nQlvv4hXZfWL3RviZ15TwrfKyxuyoQ+XUTiIplcE2hRI5QNM1xXMFOi498mFH\niWrhpB6/+p0jTZZSxvFwH1Ve8KbAfSai3StXrnG32ylzKcQQeb/4FBRimfx/\nWllk66nqSA1jH/uyTbXL0ylBA+LkxRoXn9kUWfUbQjjlBxejvBMRKd5sroow\nYsWDL/yj/H3SnuwZ32gQG3GP+t2U0dPee7ioZWncFvMTbXFF3ap6Fd6g1YZM\njHpy1DfCcQWJPG678Pet5hcUZErQBuWkvFLgdw3aZSvLvMxUa7iBPkcJgEzQ\n/imwVRrxl+D/YPaJRQVcOoFVSVhcH0rOZj9VvaiaF/lO5gkH/c63WiLym9nd\n3zB8ud/OBf64wf32IqtArjaHrmzbR7YmHFDAjk6gaiatG3tegIqqE0cZNL9p\nTvbO\r\n=cAxO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDEAzAiYP9vTZ5l8XnqpJmfEYqHrFpsNF523p4mxduebAIhAI9WxCTtQRPj0JqY4OE3ZVIslhAnCckWQT1zeB9nb7i8"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.2-rc.7_1621958786960_0.8717859111321986"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.2":{"name":"ipfs-grpc-server","version":"0.3.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.0","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.7.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"c40960358550b920d3291b8030715537a63c63e4","_id":"ipfs-grpc-server@0.3.2","_nodeVersion":"15.11.0","_npmVersion":"lerna/3.22.1/node@v15.11.0+x64 (darwin)","dist":{"integrity":"sha512-HEyN3EwHAlep5QWNshE1KIO6JylCY/fVppMtyv24lp8vz0H1isqAtHP7uZz1YjUB7mvTUbmYw+HSiQnOJwjghQ==","shasum":"475953f1acf9cdce041688ad2b0bfad5590a7fb4","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.2.tgz","fileCount":31,"unpackedSize":36609,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgrhXFCRA9TVsSAnZWagAAZqkQAImqLxiNeusUalHZBV9n\nk9WNchxe6hNs5VIiXTYZE4y0dM2PWovk+k9Oa9ZzPN148q2eWc8Dj1UhU99a\nZR1Vrr7tShPN13uQNc7XAD89iHjBWmArBQEppAvhhvPIEDU1ductk/jInQ51\ns66emsbIKdkpfvqqItaPvOSIwTMLtIPehWD9giw/us7yKBNHZNBcyWpIcr6r\njZNPUN4GtjQMx5iasA+885Y1BzfKE5X2NfTc5ZXA9Zhg0HerR16GNJcDkIB1\n3DkenOUeahgTVwxUQZs62nkNbyfTtwvngp5Z4Z1NRjN/HE9oam7UVLlXeVF2\nnQI3FWFPnatMd5wReoG+A/uQYLnjrE6vCeaAvi+hSInzdssQSr0+ceOnl45g\ng2q9aW0kXt66kCuP+usZjf8aNS3PjYvXgD4qiRnIwin6xjJZHnpduysqUoHY\nN/neZbOBSDXQ5RD+Uuv513AzMDHHfT6y464s+EqhztF2rU2Jc0QBbjCru7BI\nGRhZgSmrUIW6FuiDPZj+6dxXHQjk/h/KCl3rufoGQy5nwzTsnQR6271QC2pC\nNTQz/HDnoQq4z7gcd1l7cwkQgBeMH96Vyq7RcTbNw4KN4yyVu4CHGQGz2M8G\nQza9rn/JjnUtZcCNQ6UP3Qtl2G82Qs3iwCes5n/BpPwU71GUmmJbKdHwN+M7\n2pe9\r\n=VlLA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID7XWm9ZTNPjiiTM2YLFp3P5rUG4XjIP94jUHsvXcAijAiEA8owH/vzS6V4rvEin2l6Y3/NyFRCLMbLfZ2TMxGfz9OI="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.2_1622021572884_0.9636779856406508"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.3-rc.1":{"name":"ipfs-grpc-server","version":"0.3.3-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.1-rc.1+48c4a952","ipfs-grpc-protocol":"^0.3.1-rc.13+48c4a952","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.7.1-rc.1+48c4a952","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"48c4a9520e4ed668f4eca2fccd67f9849e967286","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.3-rc.1","_nodeVersion":"14.17.0","_npmVersion":"lerna/3.22.1/node@v14.17.0+x64 (linux)","dist":{"integrity":"sha512-6MC+r8Dm94PwcjDW9qbjwSTnjuvo69aTFf/lx6cTHijtTaqGQr4culNITYyIDEz+HfgswHy7mPl92g66g4SaOw==","shasum":"39b78e94117459f454cf9ebfa1abb817ba55cef3","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.3-rc.1.tgz","fileCount":31,"unpackedSize":36666,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgrj4hCRA9TVsSAnZWagAA7D4P+gPWV26qemlj4M854bN+\n5S5GtLMEfQnN1glgwyVoHFqH3qhHKsOe0MgFV1OvCQjaMTT1WQMylhUaqmME\nI9Rp1vMig1LgIFST2YCH3L3OVOIkjvUIC9UZNgVaDGbt/img1wvAwnb7PAte\nbuClBNFjMOp1CaXAQLUFztPqfpOEArfdI5KmB5ntivzte2AqUxyslm8MabPs\nuw6oUrExl8Tfr6jGEuqpgmOWk3/DYUseimRneLufvKaZpf+iXcdp5IPBemhZ\n1LEryovCq98u6mqUY2HRgnhMots58xfJC6FZvRPhmIEq2/l7Z+yRtMhTV59c\n4cXgdX+l9RHCusCbWmEQ5oo6wGGpHvoJXKch5Am6w01XPsoW6JI818fpMGBt\nGMuCes/FgVcglWAhht2hYDRthrMKAI4EHP7WqejaBzFjOL8Cb4YOkbtukfcC\n4Yj6DHyQ1jB9eD08V4p7eMM65Gqg8OtCon7P/4/Pxn9B3/T2gruKp8gXrAtA\nIyVC+1Y+X9PwRJ4vKRve1wbDZXtXmTZ0DvyHlWEEJ1dGYLiEiYMMX5dvx8Ll\nxxL+ccuD1fuuyRdcH/cv/HKdtkEt9VrRBd4zIpF+cQHHASKji4Rp7yee2tD4\nbqA3nBdlgJpqjidLDezakqm/8MzxDrY9Ygta3rBVFTGQVI8YGu34Bkk5jQb3\nBUt+\r\n=BfH2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/i45NASFKlC+YKuXEVlqToqEVrz7c2Sb3q+P4OWHmDAIgGdEC6MJlBHt6iR13LttjoRPEpIOqd2Gz7Rxo0eofReE="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.3-rc.1_1622031905487_0.5799643930480767"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.3-rc.3":{"name":"ipfs-grpc-server","version":"0.3.3-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.1-rc.3+ff56373f","ipfs-grpc-protocol":"^0.3.1-rc.15+ff56373f","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.7.1-rc.3+ff56373f","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"ff56373f0606ef2c59a61916f02e42ff524f16ac","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.3-rc.3","_nodeVersion":"14.17.0","_npmVersion":"lerna/3.22.1/node@v14.17.0+x64 (linux)","dist":{"integrity":"sha512-gyzahBcJKxQ4eajwzLzR9ImhQz8xser+oN6OJqKxPUWVf5VvEbg0FC+fGm2aM8Lg0F0vG1Tku6dpBzJSlVhI7w==","shasum":"60a743dd9fea4f745bb319f137141a35125cf711","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.3-rc.3.tgz","fileCount":31,"unpackedSize":36666,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgtpr5CRA9TVsSAnZWagAAAAcP/iBNW6841iBHbGU0l0ot\nf9aG6DReGjcyUEGMomHF2YrG/N/gz1C7SYTQ66sp6ghI6yTX8vXXJXBgnPqI\ntGkqYxTrkpcMezw8P0mz9VqqK1ieWxJV4LXwZEgAhDwARr+bmtHhxM0eveMF\nGcuY+SshjdthSHwAsfvY2TkZymrl9wrmTHL38aUBxvm7XYB3YvlIaH0eGH0s\nF4Lyd0MlHIxCGXpVhWRz/GfIr2KoIoumFJ/ZfDk7kw95j0+7MCIVjMm93nDw\nYi92eSV1p3DuHZeUCMyRr9jxB4JdeOolWuOd+TVyipnFs4N6jdpeR2Tu6jdk\nL+utGIAPN78EwwANtM+Wy4uCsDh5kO+KjT3s8DkBBBygXwPIB+n7LfsHMMMn\nUVMU4HCAXuraBhBYWZNwz6hQtAJS2eyRKuIjr7FLm9xviCYURsg0y9BXW/ke\nERV+fAmuFNTjifIfP/NOkdrAKYkwEH4rkpUqotAkvBT71tPmDCRnmujAPYkf\nAyaAID/rv9JkIzmv+Jw+IVK0bc2Rt3dEVlaISmjBjLZ+6rQ/iy/OdnBzz1uK\nUbRIxgQcPYBb680/XFEM+QD735+GR6bvVT1SwDlK6kQ4L1ynfb+PjbMi7vs+\nU8pKfHR3PBCjWb+Wnp7LdJ8bfFNBaMa4Db7lZewYRUkkJgNPBkD8jDrV5N+p\n5PWo\r\n=Xq83\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC2m1l2Zxsh+FabcZuO27VnWNLGZSOJ6ovKtQkRNLd/VgIhAPbkCEzld9AH+cwCJak6sUwrXr+PJfVk67ZA5ZhXMI2o"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.3-rc.3_1622579961170_0.8517219127698714"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.3-rc.4":{"name":"ipfs-grpc-server","version":"0.3.3-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.1-rc.4+c4a1aea5","ipfs-grpc-protocol":"^0.3.1-rc.16+c4a1aea5","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.7.1-rc.4+c4a1aea5","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"c4a1aea5addf902506e34d3d9821285ff0423710","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.3-rc.4","_nodeVersion":"14.17.0","_npmVersion":"lerna/3.22.1/node@v14.17.0+x64 (linux)","dist":{"integrity":"sha512-GIRBltG6R3Z8yITr9K77c48T98DjMOk+2QN+/+jFYwjkgMyOhcNevs5qVrzIIuQFNx9ii+S9UmOGJ858tPkNfg==","shasum":"ff72aa33c25add6a1a72c4af14a80f37537ea60a","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.3-rc.4.tgz","fileCount":31,"unpackedSize":36666,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJguxb0CRA9TVsSAnZWagAAsaIP/0MOassoPafLKQ3Z27X5\nL2rZgl2uW5CDEDEK1Ybz0KVX/3ZCxsGeeOFzsxNrMplxxAjB38kbCSjlTkR3\nEEozQ61P938stQL1qtAMrOTeZqUBP7hTIYOdkP9qwlHnyI+NAju9C4yT0cL0\n+Xl8bsPEt17jL/eVOrKALtmPirFFY1adVkM5d3xxmYZGeqmTzhnbu68iJCyX\nslH+ydUZGGhmR9Rx0J8tiufKG+KH7a0FoLqGYdwu7eC1qSIdKSpr9jyvffEH\nR5JjC80jEJVkw8EFMq7IGiELgVzoFLQQRXM0m+mvARdcpUhF7onu7q05mdiZ\nSfm5e0e2QGugsh7wBJOdlT1Rld+hsiE020PIWlnKlrI2pzcLQWYGY/X/NvJs\nD4SyplR9MYVayc/GIf4JK4HZF81fMXJrOIlZZpsWzmlcK6Fg0iiB2xTd5zE/\n3/2ROt5OhTgfpNRWuaGt7qFVDRsvnrky7zYceDq0b2kAWWJ9ahb8uXyFyPpj\nNz3QZiPv+XTcpstYg3FWz4l6/6Q+U27bittgxxxAliklaMIFS3O+vYfKvtFA\nKobPrXDRRygcnTjfq9+7vwenmv5XZ9OOYRjSD9yNCQGDnVUVr9qJqIAdSeFa\nSYlHJx7r/gDUiVpuVjVLJxeAq3+zqCc5xxvn/vNBtyUNZYn/ZCQVUJyV04xB\n2LtI\r\n=3DRb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC1bR8xsg5WoC8HpCiuiSCy5spALTYvaxT/i5mQYF5qngIhAOu1JsrVKeRIwI9PxhXq0u5vB0ns9bt7nmt5w/WhI6l4"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.3-rc.4_1622873844362_0.12042106421953314"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.3":{"name":"ipfs-grpc-server","version":"0.3.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.1","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.7.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"08be8beb2168f39252affc8e840ff3e185c69a44","_id":"ipfs-grpc-server@0.3.3","_nodeVersion":"14.16.0","_npmVersion":"lerna/3.22.1/node@v14.16.0+x64 (darwin)","dist":{"integrity":"sha512-qFB5MTY4BIdIB1grzewEW6wXvniryoO7tU6LZMn6AzZx7y/UUQsmaULLQqmVuN+BfsIiDwkxaqEH6fZV9+jdAg==","shasum":"89ef798f32a7e5554ded56311b55f00f273f91d8","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.3.tgz","fileCount":31,"unpackedSize":36785,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJguxqNCRA9TVsSAnZWagAANOsP/jzsoM94SF037yr6A0Yi\ndjz1Z8Kt3KXHF+M/9RxqzY3F5F8on12m7ChjjQKxHZJmCs2Snv7Y9vMFsBvQ\nThNJtgc86zAeeBzmpJKMFw0n3yQWqSwNG0YBQ1E3PkxM28DE4n9amq4rMr19\nHHRMEHi6gHdD/nAXGl6Eaxm0RnNBV+6wFeBlFtXg0hwoX9G+8ZKgSR4yrE/l\nqA6zTUqpFQLfBF7ZwM0UWI4wYUa5uJTasDbnlucPiD1Z3uUkdIDM4mUVyJk1\nX1rKVOGKGsPMwKKUMsLTmKRUnDOLwj9nI5rOcfgxYXB2hPDsOU6fHjO7FbDo\nEMj69EgBG+/b7k2414EMC+bTb7Q3vOIwSExT1zugyMXEZ+/HtnskNrBCm9dv\nc37dLHtWtOTDL7ASQzkKYfcfrqcgm1gU40nGzY1W++ze3pNQEU1xa7uNsqRa\nRqYUlnMvpFvz01UP+cFZpkS6MF4gCoYm7BYjy4CfTxAcCCdeMVue+/qnZrJ3\ng4KsjKNIWQWPC9LgO6GPJ9OVPeXXaWvAxOj/yrUJ6QPCNnwaH5Mug+fmustI\njm9aB/v8W6toNb45tQgVUvHKsM5r+x1/rm5cfypaJcsOE+2QKeATl2A5gF4X\nRYRnt5ipcd0N45gYuSWAtHr6/K1K3qS1GCMOFCYOV05saT/JdtZltA46tsXx\ntKeh\r\n=ONCy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDlmyTRzqLojp6gQMHRQjj+Jpy99X4bsLZGVyLlunfaVwIgHk8YospgVzF4UOq1b8ArPoeAaV+BQamKvgH3Pnxy8tM="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.3_1622874765763_0.770681428057145"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.4-rc.1":{"name":"ipfs-grpc-server","version":"0.3.4-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.2-rc.1+714c3de1","ipfs-grpc-protocol":"^0.3.1-rc.19+714c3de1","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.7.2-rc.1+714c3de1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"714c3de17f4833b8dcb7c0ff51536661a22cd6e9","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.4-rc.1","_nodeVersion":"14.17.0","_npmVersion":"lerna/3.22.1/node@v14.17.0+x64 (linux)","dist":{"integrity":"sha512-BY/Ur4RMOgl4n69whEYrnPFfKmO+1dH0n+z6vZwpclicAunlhqZiyPB9HYWHLJMtES+PuHZahRP3ISht4wZuyw==","shasum":"d847737a41bec6abee15e714f5345048e68a7063","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.4-rc.1.tgz","fileCount":31,"unpackedSize":36842,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgwdrVCRA9TVsSAnZWagAA0qYP+weqfzfAdRzhZ5EGYi7i\nKB5FfW8LAwemH5awOIqLUulmoMfmr51tmDCHdp1PVYGSzIVeJZdt8yjevRYx\nPow+XCXhqd0Ics0FybQPX2vu7/9daPocYhZePVLGj3oA6fxrTzAI7HTZtfwF\n/S9cmOzsj+C8XYA63Vom33Hc+wUb4ZuZoAxskL7AS2CWfpNm8tV/KAjVypwJ\nUdQKfiNR8kvf2rtgDARz5MO8z7/oO/UEzXcUX7gnxvX9sNzk1oUcjZU6YB8l\n+4zMpF8kIgsal7hsM9ialaAadpK0pwl4uBOlJeaWW8Qm/ypiZmAR9ivM5CgO\nnpMpilfMyUoKnMMe2R5YnimOxxaEcjWy9NqvXWX/4mvzGjlHU8BAuq1GBk19\nOYAv6oAo+9OJ9SmrXiNC3FE5k6ZngJhxZLyAnwT0OHvWtwzzjKz+n9cy26nk\nl2Zs6ANAeeeR1wpvybkV57aSUksDgzjdTjMuj2T/QsL/cPUOkxa1na6FvmDW\ncpLehY92NCVzyz7L0h+Q9MWLXN8Ua4l4LoZEjPwUacvzMeuvDEI55bSlAE75\nz/BtXH0nFbPP+wXl6RiAi/xNh06HZK4aCHhR9qQ8snkQdAygEh3ahS1oBegR\nosIlaB4kdK9ih+27/3ro/U3zIc6/3iZ3Z8M5cD6MVjGI4lejz2Z9e3fUjSk0\nUEfA\r\n=qW54\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCrATIFWYSiDQ69uqFCoYJGOxX0dCzezPYtYR1g5OsuBQIhAIqzygWs8ABEviZe49zFnfuN46yIkL4VvAhGLa/oyWr3"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.4-rc.1_1623317205220_0.3348512018967702"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.4-rc.2":{"name":"ipfs-grpc-server","version":"0.3.4-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.2-rc.2+bf44a037","ipfs-grpc-protocol":"^0.3.1-rc.20+bf44a037","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.7.2-rc.2+bf44a037","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"bf44a0371a53325a8ed10c93ffd3514b995185d4","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.4-rc.2","_nodeVersion":"14.17.1","_npmVersion":"lerna/3.22.1/node@v14.17.1+x64 (linux)","dist":{"integrity":"sha512-ZMGaWrKWgTDvEc3pHtfq6meqBQnMT5dU9NvQkcxWDMayl9RD1ljFby3MkX0CVC0rSw9Fk6BPJiAhsV+3JlzuOQ==","shasum":"040db834b2cda903988cf7e7c89b2737c321c2c2","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.4-rc.2.tgz","fileCount":31,"unpackedSize":36842,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgyNoECRA9TVsSAnZWagAAaOkQAJUP6ZRMpiAA6fD5dxkR\nK0P0OZl+7oSYnkKxZSDZJFoL+XjeRpNrYRYrBQkYz2J7pPUmEuIeNR87KgLj\n4UqyqPoviX9f77tgoNcadwi7uQ44HYwBkG2bn8wuikXm3w4hmMP/xEZ4Olv+\nrY7+HoD/T4ownqMT/GlWEFCDEL8X1zdYou2jJdUn7ZnR8YvyP2AEZSqDw36H\n9aqarXZIA4dodBqx4Hqws7L+QSjTgGl6DBMBOKsy1mm3ilkizRkWSuFZk9vy\nhrUEBNi7JnCsgizYlSzn8kGWRm1wfDQLXzTZ22Y0Y7tW312SNQPyrlq4ClSr\n2N0e08tkfyf9nxqvSNHLTcsmEXkhU4av+CtXWWNkBk0XQN03pB3bCrzChAiv\n+3BzjJI+nvoEE9+lwzg5qFqv13Wj7bOK5semtHy7Y8TkZphXnRK7oMb7RW/U\nb2fb0FA5lIhewxI2dSw7T1HB5qQpaf4s9qIwuBb7P4ST76ADI4hZ1QKbRQb/\nsyvQw5ZYnr7s1ihg5IzDEGvPa7H5DAF5uL2cnL7BYkYY36vCWxaANBuC4ceU\n5qIt0y7J2F+Sy9nul7UBQsNXzZ1dn74ckP7ojus7Muy4bxql/njqIhAWpVaV\nEg1z6z/sYvin3zfDvxVgKuCN84H/wdMnmV021GBGa2PR/hehQQVRcCWyLiV5\nEWpn\r\n=Vu4j\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFwE8oRMVHzp9GCkuweJtl3n0mrDe4KOj7H86yR1hjFcAiEAv9TR+nvHDCf6q/h+g/TB+WjVyZVfEvsRDPuKhdLEf3o="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.4-rc.2_1623775748226_0.8736333723744452"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.4-rc.3":{"name":"ipfs-grpc-server","version":"0.3.4-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.2-rc.3+b1bbf5f0","ipfs-grpc-protocol":"^0.3.1-rc.21+b1bbf5f0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.7.2-rc.3+b1bbf5f0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"b1bbf5f004fde7a26f8cbf6e0bd7356f07dddc94","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.4-rc.3","_nodeVersion":"14.17.1","_npmVersion":"lerna/3.22.1/node@v14.17.1+x64 (linux)","dist":{"integrity":"sha512-CdeXXEkiY+QNDz2MubIvAWiob5BxELnJ3/2+mHMlhI6M8R8tt/PQor+iM3TjmhU2i3rKdXFcmBCGlnZHrd7C7w==","shasum":"513a5a9c552843b57dc87d1a20a1c06991eed162","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.4-rc.3.tgz","fileCount":31,"unpackedSize":36842,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgzFUwCRA9TVsSAnZWagAA0rgP/3kYhoywpJq0GcMLgELe\nV3m2Zrsh3hnzDEZg7bViyTOuxlGP+6QaM2QjonQqkpjzEUx4wlpmOh2AinyP\nFVLO/Io8hXEsqsTm05Ta6bgaWm1SuPicagV0UGJQDyY5HCEQT6KS6E6mkGj/\nSbaTm7uHBhSQ/G8HGcCHl5hJc67bC/QNHDqB3YwWhVf8oVkQzaZ4c1+PZ3wM\nKfhn6n5ZuSM9t03EtM0YMHnzLYEcbESzbZx0+SpOS1os86hw3V2f9npJFDjp\nBDoPs9rGloTfXwlqzfqAzaARsghoeoUP/+5kaGcbquOmD/K+d+U0LzU7Yqwe\n9sL3zggA7835ENv7uMdVIz0v7/MzKXY/av4BznChGI2XRNIfLI8vBMHkKzSV\nF2zUf9E/1b79mq6jvFKJ6pUL6pM2825+IyhC4fqa2txrNBmn+TJzHw9Vw/El\nX4xeu/XaUg+Pd9887ZZnx2bHLCDZ+h3jIEE6shkvv8BMIQxfWydv5Rvpilaj\n/1el05i3f0+ObhCtjxszPKB2OQE0JDURugFMLAEsng96iQSSkAQ7k2AaTzuj\nnDdY5ynMmUVB/zu25QpO5b9gPsuMdf4/Zq9QtYY5iKjR6tytkxe9Fkwucums\nLodGtinfHpM2O/qGAxnPy5fPysStYc9hrHZ7K0Zb69hjqO3HwohOxfN5zIjZ\nlhgG\r\n=m5Un\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGi1VAteSOakrDQaV47L+98bG8XC/psRH+9zv6TaQCqhAiEApyn+2WMDd3FNke4mVW/j6qB8OXket7LhDeMy0x2Opsk="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.4-rc.3_1624003888470_0.9755905986093678"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.4-rc.4":{"name":"ipfs-grpc-server","version":"0.3.4-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.2-rc.4+7c1afbdf","ipfs-grpc-protocol":"^0.3.1-rc.22+7c1afbdf","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.7.2-rc.4+7c1afbdf","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"7c1afbdfafcfb81f698cea35cfa0e392711d40a8","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.4-rc.4","_nodeVersion":"14.17.1","_npmVersion":"lerna/3.22.1/node@v14.17.1+x64 (linux)","dist":{"integrity":"sha512-SC/Izsy3bfOuWwizNLg/wKzUQB4XwHzocAbdcV6M38CLSXrzDAk+Q5yJ0HLGzXrOG09lJWNlZSjkdoAumjzfGw==","shasum":"324e20fee4c3aabe4ad499f6c1e38f05fd694957","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.4-rc.4.tgz","fileCount":31,"unpackedSize":36842,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgzGWDCRA9TVsSAnZWagAAfAAQAI4sOkptkvRfQWZnmtIJ\ndefLBxp32lHNrzNo3LPL/ALKdsYl9By85m7+3NFAqNgDuAV6L+Aq/A1JTCrR\nFhTKee9F99azON/GffxtQkNeCpGUfC4s0nGo6xkdNePaWd1qfRMhCUBu0iCS\nFsiW4Tk/P74KYT62iXnyohc0QMexOQAXREDBVaBNJ+tE/MPuBSWv3VWK16OA\npCD93KRc/0jpc1IQpW2FbAy+XUPXk5Tq+FRQHoizhgHVtr94XJveJgV9inxM\nqYQCpPea12dpobwtVrfZ3ZNVlQ+Bxzw8QACe/2N1rGuIoxxGFARjL+TPzPOn\n7ukuvK+tKhMTGRjbo7UCVbTHk0aB13sVELjSUw6HUbv1bLHWvsVEkNXr+XUa\nVNGXNK1y6ivZl1nrDKHCcS0vJBrFwIRgIiuvndZGW2BpqcsVoF0s0Aoun7IN\nP4m3pHjyKWgM1UUHyww2hM7uMLQvrwVvTLNbeYQaMZHLHfWHwCH8uNwIOzVk\n1tU6vMwPN93be2DfbvySMCWfhwprFQ5M+Ge0cAkAZvAqtCRqaB8W8djPqFam\nn6PLvAWjvatKc3DFsYPbFQMyi7KT9HdG4C2kkL+z//ERzmabGSWkSsBcP9ns\nAEuOjn01O/sDcY/mrJSJtFE8gI0gubcgQ0S6+gkQl1nd9z3+B/d0jc6d9Z4U\n0cVi\r\n=QUYf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyYF5SBbIi1TQSDr5wZj5feyFRa7lY62wEl8EbIBpBtQIhAJRaTcbRTR3WeNzxyskFSHYhDRyOx0e3xJfk0ppEE5ZX"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.4-rc.4_1624008066973_0.29007089861112045"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.4":{"name":"ipfs-grpc-server","version":"0.3.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.2","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.8.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"81f944163f5a78ef15fdc23b2c488ba7f44af0be","_id":"ipfs-grpc-server@0.3.4","_nodeVersion":"14.16.0","_npmVersion":"lerna/3.22.1/node@v14.16.0+x64 (darwin)","dist":{"integrity":"sha512-PqGwDflW7z10zXR2XGjFd9p0x5foga9ooCcG/AoHxNCO1XVM/iuZp+r3kGu9+NjpX/Z6EcU28+a4ldY7J9dwgg==","shasum":"65292470be487418927449ec52eb94e8c4502b97","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.4.tgz","fileCount":31,"unpackedSize":36961,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgzIBoCRA9TVsSAnZWagAA4xEP/j9SXcspWjau10tkluc/\nEner8DWDP4CIKzEWLwO5bZgcohT1EJo0NpbWtolqxrJaUpTumoi2wuu0u42Q\nK4WKVMz1GLymZtdu84kxiLFDQ4uuEa2GXWBiQneKRQGRYvn8V+gxvjiClswX\nRQJONj9rWLu+crV47bsxZktDJ6wCqFNG1Et+W6SaDO+efyIjLe7X4h6VmnM6\nWFl41PHQFN+wkFTDaCrPU3TWGvPfBrh84EONupyCisbVqeocT6J+prL3rd12\nBw12QrozvL3ievIB4C+HQcKQBjxWRww5pZipozD1c4hSOdRxN77MN4YrF7SP\nrpCZ/NA5sRO9fYgw8qYk1zvjtrpPEd9gncHB6fP9M5Lyv2CZcrbVFgwTkL9P\ntPHWsTwzINrzHPAEO/VGpct+0wQmN+6kbqrm7TxDLkAwoc/94Z497PKqebVZ\nxw+2XAwl3tKZ+UHMBcUFIykliZtvpU4tn79YisOsNKMVRvT57FYpTFNVQjpy\nToMypNfSQgg3GXzzvZhPsmkuxTJdKxBMXP8UXpMtFE7Ub48atiIgXCltWNMu\nF4EAedK+diz30k/q0gS0qZbI9Jldr4RXITQyrwvLTSymX3fkDRLtjXau4p/K\ntUF/Thi8W79588mRiFsTLa51GyPHlwGFcbka9scGITNqathDs5Rdg0GVEfTJ\nI2bu\r\n=vPnn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFYtSFwNsz+tInUDJ8snIv2JlbnIvxqqTYZyI3wnRH8uAiEA3rCzN0/66MIQuofdD5+7OFXGvqIL8pQ0uPYNEfLGwKE="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.4_1624014951880_0.7939079082464622"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.5-rc.1":{"name":"ipfs-grpc-server","version":"0.3.5-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.3-rc.1+f4b2a8c2","ipfs-grpc-protocol":"^0.3.1-rc.25+f4b2a8c2","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.8.1-rc.1+f4b2a8c2","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"f4b2a8c204271922ea34ef8c060592eb56a2a1bd","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.5-rc.1","_nodeVersion":"14.17.1","_npmVersion":"lerna/3.22.1/node@v14.17.1+x64 (linux)","dist":{"integrity":"sha512-G2r/kAagtvwpO6C1KUq7uqg4YnjyQ0eJR4MXVGy9bJ9z0QBO2zwg7BoUcXwYQTIWFfXJTAocnIbzy3hH6h0ubw==","shasum":"dd38cf365195a37cbb64d0c4b367ffbb617f6036","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.5-rc.1.tgz","fileCount":31,"unpackedSize":37018,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgzMKPCRA9TVsSAnZWagAAhTMP/2QtTSN4P//2n9ZbSHjo\nOM5noOLUXai6/r/iJBNgOyRWN7PYBbnXT+7q3whQYh3OD5tkpv7THNmqNesu\nOMeS7ALD6YBgNoPaNFaHxKZbs6apxTprOS278v2jG8f7G+7yHotDv3+UpCQj\nXi1t0ZolG7qNnjcXL4bY4glmmfWf7o+s4x4Bz5uUEnLgauPQb3vEtPtp4ER/\nNQZTBPgi6HBoSQzkbHADhRMHvdaRoYsUlSaU7rs+Idrexbew7GAduPNr8qFP\n1zgr513n33RO/IE5Fr13EOX9Gqjie26hiR93/+euiCGtWHS1r9jO2kvW7iS2\nYAHXv22TQurJhr3ctxz9Rxf1itt6qnu2g95LSAZsbRZLJ76U1vw1eixyciPr\nyK/p3NbBleKKr6gPNEyOT43YgC1EGNWerEa4SH6MKOJIeKh9pfvB76LHZab9\nwg3a8H+yWNjEi9oc1iFQ9l1Zi0+dKRfeVHuz9JJaDfvSxjw1lieh5gw0rrWo\n7gnshzUmgcjVuh2OtkxsdKTPURChliXHJFy5UwfWk0fh6TBaKyZ3cw97i2Gz\nqHjrQn0Xi+6zjt+hvJHIbISPgCcDuJ26itO9KW4jCRBc0IWlxkCu/ZWnfFin\ntnoQ3Att7fNEZ5okENB71SWyhhIpSF2QE9SiTJckWLlgtzLqepQZw9mYTb4g\naRMz\r\n=FR6g\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHvFF5j9JCyE4q4DT2oYxw/Ff1/KnxWFIqZIYv34q/j7AiEAmboX3E5205nPllNGYKCUzFGH68+VAU3I7sJlj1LFGnU="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.5-rc.1_1624031886998_0.7364469111419039"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.5-rc.2":{"name":"ipfs-grpc-server","version":"0.3.5-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.3-rc.2+4a4a360f","ipfs-grpc-protocol":"^0.3.1-rc.26+4a4a360f","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.8.1-rc.2+4a4a360f","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"4a4a360fbd368b8b27653a81c9301820c93d91bb","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.5-rc.2","_nodeVersion":"14.17.1","_npmVersion":"lerna/3.22.1/node@v14.17.1+x64 (linux)","dist":{"integrity":"sha512-SvXVqYjbbEf51a+hL3hVFYWGmVzgXnmolzmOCDtl2koM5nKPuX0hNA/7HD2zc7sHYLZbxMb399zpNSnLee/Jwg==","shasum":"590569407ad5f393af9748d1716e6a7a7970a618","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.5-rc.2.tgz","fileCount":31,"unpackedSize":37018,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg1fK0CRA9TVsSAnZWagAAOgUP/AjevRRqgY1BYaprSQ3w\nXWutkA05OU/wzQGcZ5kaeRdndz1xCgp89Zjtfi/c86c1hV7H8IuiOfLiyLNy\nknnyjq78SlZlo4YoZNbJeq5vdewq8czEuu9lQDfqz2U2HvZiQ1JN+ua5U0fG\nlZy2PhQIjNmr5BAcGxNQkkFOZmnVHfhywfZiX8nCLzerG0p/Lk50KQqfmq+O\n6pDkFo+2F7Jlz1H2npnjPXiYXQIurwyywPqK2cf8qF6dslGrq1kkDcFi0LX7\njd6vrSahLpVghRICqQWnneKbkEFsDeVNOnHeaargtgAldXEnc5g0cDXBMmiI\nUcm/R2vP/yWUJUVKBAwxnyGNshFEweO39mU5se9R2tpGO2EjbYfHtuZ88uBv\nGKEsZOi4Xg0/pNyHHXi7l+trouBKIAdlnZkCQLLNRwPgiWzAQ3BuxfLzCQME\nEXlyCM38aEJQaIO69t9pyv7C1tGNozCsqQ0XsDD0KMPSE927Bxxf1LXROfZK\n/NJNGhWPnm7trqOF50+GVsAd3ACIbdMKoUqxnk7ieiT67yNJX8EJwaK0I+sB\nWWHuaO5HvauW/inRJVYr0NYkyCuhNQ5XhHL9iDsjsLvzrFM0CDCVU/IiJuPj\nwd8zPv97w98ybpvIUqxoHOL4Vojdk3ttNl5V3jeyvOg5vw/GV4/LHqFuTsuK\n9/V5\r\n=npsM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDU3xBVMQIFuXQgLFft5ZCN5siUAASQWaKOEpOab9vXqAIhAPiuBdyj7GtE9icyOSVCDGAV1QUmKrkOYKS0YM0+RD4Z"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.5-rc.2_1624634035849_0.8516605597391893"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.5-rc.3":{"name":"ipfs-grpc-server","version":"0.3.5-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.3-rc.3+88dee13a","ipfs-grpc-protocol":"^0.3.1-rc.27+88dee13a","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^9.0.1","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^33.0.0","ipfs-core":"^0.8.1-rc.3+88dee13a","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^10.0.1","uint8arrays":"^2.1.3"},"gitHead":"88dee13a9246d841648d31edf0db62e4a4f859fc","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.5-rc.3","_nodeVersion":"14.17.2","_npmVersion":"lerna/3.22.1/node@v14.17.2+x64 (linux)","dist":{"integrity":"sha512-BsJbIDsBbdoJnjL3JQmrI0JIL5EfgrwyVa67+Tv7r9F3CRbg/CcGjWEb4iJ8VPzWkmXcV+q87KAXfBlW77xFFQ==","shasum":"f53321ab48fa4729ac208ec68b99ba8ffb3738e7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.5-rc.3.tgz","fileCount":31,"unpackedSize":37018,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg3efdCRA9TVsSAnZWagAAWZkP/iCVpkMnOYk+4Ew5ndiH\nPtSilTybBP9nPh6RDt56z0ppq6rn08OgBubgiU4satZc5KV9LEJvpXi3thJd\nh2WqVLrClybzkGMQuLpojYQk8nKzl7wMT/kP+Z6H8eAhP/Dy7nIdg42W7O5K\nuDuDz4+mrWSkMCn5JXesp4Ep5y+2Ctif8phOIfvPwoT4K4Lo5MP1Qr9ZcQCm\nTSP39oqzIW+nglYQ18IFH5lHJoTxCrODcW9N7/Jzs/wp14Jy2+ANX+oxXIGc\ndDiRuDSD0mmIhByAOQpK4qfe5LW7gDx/CWjij2H2xu5I+7/x5xdqMyK+OVJl\no7UQ6gQq9qlo73vacD+epqnePmaXIcKplRNZ8n88i3quylQjsk5Soki0mom8\nXBHOKuL38nC493fqmQBki8d/vRGeMIUCgGK2Co4CbHOdkne00HE6rZBzMGwD\nmUNTAjVSoh8QlqiKOd9KpQekK2PR+M+T2jdPIMiE/YuM+AB1l/AbHdccsS9q\nkbMqT7bsq1tik9BHRwkeFt7g/XXhDitssQi6/Aqr4+6dqOw5tgrL2pxwQmyn\nf15AfQxl8j5SantcTgfC+5M3TnMjcDsZ67gAvog6zxKfsrhw+usNi6PWL8Er\nQKdHt3/yxElZ38MCDePqQJF9KTq8TFlw2iSqHwhtep+Qlcx12jDL+tUqcO/2\nZkOw\r\n=w76m\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIESBNxDXrxdCsSzrTuYLqMfbMzHQioeUWEGkkbdnau6+AiB6z1eV6SnHsu+mF3dT1PVkBhtf0lPrZQdS2WP8+NC6HA=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.5-rc.3_1625155548907_0.7290906871459302"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.5-rc.6":{"name":"ipfs-grpc-server","version":"0.3.5-rc.6","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.3-rc.6+4155de5f","ipfs-grpc-protocol":"^0.3.1-rc.30+4155de5f","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.1","it-pipe":"^1.1.0","it-pushable":"^1.4.0","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.8.1-rc.6+4155de5f","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"4155de5f78134a6cbbaa4551d1b35e8e44b580e8","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.5-rc.6","_nodeVersion":"14.17.3","_npmVersion":"lerna/3.22.1/node@v14.17.3+x64 (linux)","dist":{"integrity":"sha512-pPmwt41g2hmQ3Io1XUCVsr8uoJdu5HeEy33QCTnO/TJtJGf/cdm4wIBLwfZO8ux9dUqMNcCrJ3cZnb48wALW9w==","shasum":"bf723ef24974102f98a29b51c41ae87c33da1c7d","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.5-rc.6.tgz","fileCount":31,"unpackedSize":37047,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg9ZrXCRA9TVsSAnZWagAASb0P/ip26zvgO1CTHCbsjzVf\nzOEDTeLn01SJRDPUXWvPgAEJJw/1VhXfzLqEMq+APeRTQPv2LJYxzgNrMOVr\n5uvTV1BZn1gs+ak87v/gBRkmD/F1JWfxqMP7r71bOBCkHMRzqiRIHHjtzQaV\nTm2pTRt5r9rg/WFfh4V+zPEgcO8Se48cEYyfPvpEpJJByFEUs3vurEpJeaL7\nV3+byQGwZ3QEa5qkigF6yMNhnDVW68Og/YJJazgiIx9eE15AZPuzDOFoI/4z\nOTBxgwqr9ApGWdMUcdahpkqFJ+J7gg8oBFdkE8gj0Wi6ExQyfyHBRc1JJ8rV\nbnXur4xYl4keIhvDSODng41WqKhQQmO+VBXvY2c+9jykLeL3LmykzRAobDWV\nBRA6wuCgvytYfGkL8YMrAOgSHulCBmxY5ikp28kNOVS1iwRgOK8m/jjZSRtG\n0AKgKx9vEB0lHEo65sCUYJJmWBvVHmcDlMQleGaOI0lKSaDAAnjutl8iQhH7\nZlOkbh7KFozOJCiWdeSd06tBMzPzejQv2aXouNqnFmNt8f2qTzhDxwODHq8Y\nN7M/tc648x6oWGV5Zd6/qGzPaWUEDj8xCuFZXy7AbgYRK4DYYnn4mRDqS1Vo\npHyGPQysobyR3KfGlM0QDDopZf8hPh09fw6xxJzR6EDO6XQuE9vgxeMCiU/P\nWQ9O\r\n=PSPn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDVSgv1YKVmfxph12dJdZM4B1mVC/xqKcRgGk3wEK3OuQIhAMtSqgDi+/LUlJCBRv3D0rw/PWz8CPQx8wuVrs+rgP+0"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.5-rc.6_1626708695258_0.47659157935709007"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.5-rc.8":{"name":"ipfs-grpc-server","version":"0.3.5-rc.8","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.3-rc.8+50361a7c","ipfs-grpc-protocol":"^0.3.1-rc.32+50361a7c","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.8.1-rc.8+50361a7c","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"50361a7c0ea69489bb24f6922319601e3fd919ff","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.5-rc.8","_nodeVersion":"14.17.3","_npmVersion":"lerna/3.22.1/node@v14.17.3+x64 (linux)","dist":{"integrity":"sha512-yNtykWFlnX3NAt/PkZRbkdNdf8IoUn1K++0i0lR4gLVXptRuu7Fe1blzwKYMKgb+GNfyOULzX11lAUgz192x7Q==","shasum":"986b0db1aef531f8021d058fdfec70e0fbb0936e","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.5-rc.8.tgz","fileCount":31,"unpackedSize":37047,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg/9HdCRA9TVsSAnZWagAA/qsP+wUIWUvBJLswX/scThF5\naj6Ado+lsFulMWJ5XLj92NuKt+QIihwOJCjVF7K5Co5XiJFeDnc0WBPb70K+\nl+pobKRGZxuly99s5SDvPEVJZR9E/j67Eigl0lq14gQ5fu++HUIthBVpg2sL\nf5o7Dr3aoJ4H4rj9ed23dp60UDpmdSrYzL4GQLkWLc6kQmc0mRHUPoZqWHyh\nQ7milD9qQlTUQ7RCVoLB+BjbDTKXjdtL3YbWl06kY8ani4o/tHkhlPyRSl4T\nr+mS6AX8jBkwtxvPqd764he8AfPu6lGq77vabVG/9m2G46NsaeKt0y70+Q2X\nqYod0aN8whc2fny00HgoUo6QBYwCHIjMGT2ST+dzKFET+lP9BSkTo/zMtGVc\n2awG+pnuiWuTcIeOGM9yLNTEgR+sLdOjmxb0kSBHG8u3gM3qRYMPckqgOHzO\nj/Ztcxmfl3yLa1mmGGTTERpnHLEG9f18QXeRqfeWgvtdWs2HEPku+ga3RgLG\nOM2gW+bgNqW3DZVAyqBCxRPq9Uh5WGilfyefABocUIe425Emvmf0oj+J6whk\np7GR2L6/faH1RldjE1Qb8e15Xu02irT1DssWRxACuiVJeuCCA4xBL5P9vVTK\nA9PJRBz+PZcGZZ9Mm46OM4OwXgmn0STG6H3n3Sd6qEKm5VD+ZJ1eO+1xNzHb\nT2M8\r\n=Ttn5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB9ksLW3OtTCoefvoSC5I6+m6DGdJ8xPTkQqRgo1nqt0AiADeaoI3P57rwS4gpnQdwRWjzRWLhQo/y7mkGKzaHo0Cw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.5-rc.8_1627378141575_0.9087058331402988"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.5-rc.9":{"name":"ipfs-grpc-server","version":"0.3.5-rc.9","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.3-rc.9+09dd763d","ipfs-grpc-protocol":"^0.3.1-rc.33+09dd763d","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.8.1-rc.9+09dd763d","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"09dd763dcedbdbc52c590150bf9788c3f17074e5","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.5-rc.9","_nodeVersion":"14.17.3","_npmVersion":"lerna/3.22.1/node@v14.17.3+x64 (linux)","dist":{"integrity":"sha512-z6VjEVaALNR+4cL3iP08V+Mc5/gS5/0GaEQoKGJ7FanRyEeD1MGvpiynt63aNEpRQNLD7zQebP1r2dv8Ln3oLQ==","shasum":"0ab049d960b62762d10ac877eeb4876246cc1801","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.5-rc.9.tgz","fileCount":31,"unpackedSize":37047,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg/9lxCRA9TVsSAnZWagAAFNIP/3hs4rUSb/c1WvUN9gZs\nE4zwBeJShEh3XtxIN2XuLEH2NJIOGsAFQod9d3j6x0U3cKxJfFESZ9DJcE5U\nq8ftzOcwt7PmW6yivlPQq6Zjv81GiYl7J9I07usr/At6qEfARbFX+yqR7yxb\nWmOeVyqxsnoA9NAh8HGYMTV4GnB+pzJuIwUS1pO/GPUUDpOZdl+pTgeF0pZS\n29A+TgJEIRv3hklQulGYLM2oVzAltFfGPErvfyJK6I/GvS6sXSCbDABFqIs4\n+uFSo2yX7NKblBsivswmI/sUmfnmGNrFg5SSUoAKOU1Yp3tV91WcbPLfyzmV\nzrJvxtGapDDRpc2H0E68iC+C3iZLiE1mtvsiDCt72rqqhVCVgn44z6Uul6IA\nSi4ac1vA13krqVePFCJMLWEUHhEFhJQ2Iz+IUklQnGyMnXFjxI2SYb1NySBJ\nYbEuXxAncx6246vXQ5CICqr1RBNimnE0KQHPcUEp3vpXJNA9cWF9ij0vOYjj\nY4mHDVTvSfISI8aAwU6KcyjNTfV/uVLBWmhAH0eBzRRYCdrSaWvaIufeOW1W\ngogPox4P8ueMBAzPdAUtyHHlRRClHCbsgpPawxayl6oVa7oNsgn5ykuYnFlT\nNkk9ftNo8l65fZ4X2VrecyfQ9VxCVpwkd4N6eATm/iAnQyr+fW2l++AjKQNd\nBlCc\r\n=GNfT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDI/lw/bAkLj7SZYN2ZwRMlhEzlmVhQuqtdvLgJ/9D26gIhALaZYblB6M5CFJiWpzLE4Ia97HrAstoOnazsa0A178Sa"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.5-rc.9_1627380081359_0.772136080480309"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.5-rc.11":{"name":"ipfs-grpc-server","version":"0.3.5-rc.11","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.3-rc.11+32f3424f","ipfs-grpc-protocol":"^0.3.1-rc.35+32f3424f","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.8.1-rc.11+32f3424f","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"32f3424f86c9c7bc28155dbacb12edd97d9b84e5","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.5-rc.11","_nodeVersion":"14.17.3","_npmVersion":"lerna/3.22.1/node@v14.17.3+x64 (linux)","dist":{"integrity":"sha512-dkiqP6y/5aen4qK8UV3zj9oEMK1RwR8XFxz88elUHmXvQFuBqNmC015lMMVntyCC3w64WT3c41cEY/I4vBTJJQ==","shasum":"d8e415b45744ef31ab58f6ed3362a0826dc0f2ab","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.5-rc.11.tgz","fileCount":31,"unpackedSize":37050,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg/+JICRA9TVsSAnZWagAAhAsP/07C2LYMeG+M9VxGXZ1p\ntbcb7sBlXeInIIbwe1aGOG2WeGaXnWW98FZ7aVrXMnpigm2yx6wjFBSHcRhn\nUnz0+BqA89w7g7FTPse3zG4CTgnyeoADEaGAre//HlrlXyTq39873B7S2eXJ\n/ZZELLPw3PtpbVdlw2swK2wZY3oaz0euoU2Z6qXh9z/wL608Vki+tbNDM0Dw\nUNxqauVakDyU7xbC20r9IstUAZhsvYPd6TRkyu1+UZ+gmytVNustpGoe6gVU\nYvivSHcKMplZrnMYaKrf3GzB32h/rfsrVsoEXuW0t4+G0lGkNU/uk+sRXZuy\ne6J+WAKRXKmxPbY3oMZDeveqY3IEqN42MMkpwac1b1Gaxj59b+tYHM9FFaYy\n+RI1EYnbLurT/cc0E/nWpPuef7O7lf6a0KwJ+vd+lf8kbnXW6FVkbsDcYg7z\n2FHkC07htFSbC6o9oEoS1BYSXGBYopKvaQr2YPgCKXzjHg7PZXjfbvAlIxcy\nD16ta+sGdgWXeIFut//lcne4+oauq5TJD5zlo9wJuy9DKAiRed+wYiEQGXLi\ns/M6ZcvzkBLFh8sklll9FZ0tVp5ZCPDZsMHXjAs7E65u9PEv/n5Tb8Cu5wIB\nMGGFqkqQwIQWdK23/a9Q0Yg6Y1gfrui1dqCUMF/yCGjMqgHI6/X2dtWF/Pcl\nTthN\r\n=jVPM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDec1NFdZNENFcYGeEARw35zQNyrBJFjfBcjbWEK0kXJgIhAMGeIT0OnuS7QyP3LM6ZqwW8zApywMfMa50qHGByeBZ6"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.5-rc.11_1627382344581_0.1696613277159955"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.5-rc.14":{"name":"ipfs-grpc-server","version":"0.3.5-rc.14","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.3-rc.14+71bb03c0","ipfs-grpc-protocol":"^0.3.1-rc.38+71bb03c0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.8.1-rc.14+71bb03c0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"71bb03c0a3d5e64a1ba617341cd706c83a7346fd","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.5-rc.14","_nodeVersion":"14.17.3","_npmVersion":"lerna/3.22.1/node@v14.17.3+x64 (linux)","dist":{"integrity":"sha512-BDsownkb88FjZ2QZuTggCmkEgWGm0IimRW7L8jNbWDxKY1gqgebcdyp7T96RAfGY37b+CQSRwltEQvAF8hT79Q==","shasum":"d63d039cb28580fcc870f840e12fba7eef61cc0f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.5-rc.14.tgz","fileCount":31,"unpackedSize":37050,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg//n/CRA9TVsSAnZWagAAb0IP/0O3BkUfYdRzxxK93vaU\nEtb1FBwToztK6Er4Y7pkCPZwFtViqxqapLZpXPuKDXKqTy68478ni7CRwbNf\n+MYPRBmqEMt4M0LxrQ3B3f6OuzK9AsXu6jxrYJjVuvZRPZTZihqPm+Mhj9E2\nVSaf5Sy4z1y1/OPEFzTOfYMMsb2c0e7tsbtJjWnBlJxr+8hZZMYyLkJkynTf\n6u1ZqE/WAu4aAg3H75NP0SAZ3tbcz3q6YVCCon3WgFl7c1Hls3vU02//MNxD\nZ1L2bgP1OBxQ0gdx4t8irgbeMLaYBbohGF4s+2WUe9sebhrv1dtbV25K1Qsc\nlh4c4gerOgvd/ATIJaRiu5FD/5o/dPuEzM1QjN+LDI/j+8p9M6sobopNJi11\nIH8PHOzOWD0fiWu8h4KyfO+Q2VM+uThIQgoTf6OCaL6ERkLrSWzMc3MFiL7k\nRiq6t9QsFl/AOg8z/FGLCm87xYn/nUYZYMPJzlK+6Cn0BcOa9/ro5yIT5tsQ\nm31jJjxQFkvkt5YzwCijYEVSRIzrODkw89irGU5LAiiDLVTXwVsmJ2kx+aLj\nKNdz0z6DDUDNsBBQPbbgLtSClZ/egghuMuQ6L1GM7Woe1ooyEub5tkSXsuwb\nD+rKpKDFa4NFQG9AGX1tQ4ixxgsELJw846vdqjxkxbkDYg1s6CUSfpKB692Y\nKQaN\r\n=15am\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICsYvz+I3TL3ympcugjd88vJrFuqIZCjMdIp7yj0B6swAiEA/9RAx7i6wSC5Gr/e2eYB1W44/+sElUvDqZBx7TLddro="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.5-rc.14_1627388415435_0.8587111865391022"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.3.5-rc.17":{"name":"ipfs-grpc-server","version":"0.3.5-rc.17","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.5.3-rc.17+3aa4afb3","ipfs-grpc-protocol":"^0.3.1-rc.41+3aa4afb3","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.8.1-rc.17+3aa4afb3","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"3aa4afb30b2dc88a8b3cc2442336fd2583e2b867","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.3.5-rc.17","_nodeVersion":"14.17.3","_npmVersion":"lerna/3.22.1/node@v14.17.3+x64 (linux)","dist":{"integrity":"sha512-5fr8efsADM99cMKrs3QIgDtS9f1f19tWu2rfS9pTmhTSvMu4zuty1f7JgMQAnUYhNU1326WmKVnHuhOKXqbpPQ==","shasum":"99922e46da24809434f8f04854735bd72ba20810","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.3.5-rc.17.tgz","fileCount":31,"unpackedSize":37050,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhABb1CRA9TVsSAnZWagAA6zgQAJX5+7MrVuWun3Y8c2by\nKvbklVpCbkeh5T6SiYDvdk9ARSuDONPqxmfyIS1uIgyEOYIY709zreot16Jn\nnYgeGiZPkS9INYoyoWEprQ5JxFJpwV5lKy7c23LX0Vp3dQfT5cXwrvHfs3dU\nKcO/I2oFKeLGYjWMr79/mCEBBywmPD/rXCABVNAWo8se1A/+iA5Rhg2qFOUd\neEyXnIEdLC/1Ob4CmmaHOuk0LC5o2FJnWvDXUCCPGSlYLb8+GvQRkOQHi6Zy\n7HTYdDEcg1Aa+jaJPVkhL5+PWPBgqg21ubF4skO/tQ2r142x8+LqM0QzrW/6\nOODuyI2X+3DTqUGsFr2ZnQPuPiyaACk0t+mrKwayoac0DJsjy11bcEk1msy/\nbTUWFUkl7lt2NF1F1CX1N65S2IBB58xM00RcALxiKNrTISFK6Ji+fbbIS6Qe\n1AOUxU0XLZl/+Yq9m9otn493padGL5h9j/bLayWTSg3NqL0Mnqt34kyQn3n6\nm13OH8Ipjw/Z+PPYiSLYtE0BZa3t0Okz1vNHBkADIWBxmO9etJytyzl7cyXc\ng3yuZTlWsnKU//Dr4IRnBEsPREo2koxMJy3q5OpIvYeuEcDW9MDmVpWQ4mfX\nDAojfGQM8OCCL6irEm5sjZaDL+JcFOQ2a+6H6s2ZTf6MuSOKvW2Yn0CdeIqG\nS4xG\r\n=rDr+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCdanX6bBZ5S0PiQVvGgy4uAH/uAvpOvgNp/dPdrdGJnQIgT7b82KOPt7fq/wZHSGS8Sen+EKhM+NYclqb3XOLsPK4="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.3.5-rc.17_1627395829780_0.9859653774378632"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.0":{"name":"ipfs-grpc-server","version":"0.4.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.0","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"ef41f924e415fc2acd30032e2b484bc32f042790","_id":"ipfs-grpc-server@0.4.0","_nodeVersion":"14.16.0","_npmVersion":"lerna/3.22.1/node@v14.16.0+x64 (darwin)","dist":{"integrity":"sha512-dnG2VUT066nnT3qX/YNkojgDGRIhCc06TPpuIWNQocKMp6Z9W2uDAu6D/LqDBuoGkiWj0BUnBL38+cQz5fMnhg==","shasum":"b9953bfc2492bc7d9be6dbd0c96346e7a83496f3","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.0.tgz","fileCount":31,"unpackedSize":37785,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhACFICRA9TVsSAnZWagAAO9kP/jWGPjQy4C2SMvIx6XEC\nKpIN3tEYRr9FudlzMfT4Hgx3MNwJv44YUviVKguBdE1HlV2DBFM1DNvMw5Dm\nQSYxZp5to11P1u3x2IsnjofTWmBJ60DorsUhsVgqWQvoTaZhA5y+F/IQjOco\ndgEWnJfXmKC5ks/lHJOevkzLalvdgUxqtoGjPDRosk7Ri5XVBKSQOXVFte07\n9yew4oPYcTp/53VNjqQXQlP7MzK4CZuS0ah4zGsJOI+n8qmuuq7uHs7l/Q0x\noKTDpO/j48irhvntGnUwFZil6BQk5flstSvuTABuYqt09uJtMGaKD+5ao0rn\nOcTrwqs3Hvb9/SiTDmvueGiPSRjb4uegv1Eh1Egm+Rnip7AE/JLmC0CmVnG9\ntqCLfNSuM6H4crhtKrRDcDgX3Nte/VZXtXoDYcAysBZM3ujk7DyVe03DiZHd\nW9iYlgSWyHQpW1PdgXvAsNp89ySGOWb9yqPXCAwTJuPqjW9N8c7ZYC0ZS9Ud\nGCctSdTjv9Z7ksrPgavrWBOJ2mlogQcTrCvzYiu2l4XfCGeq05RjwIb7uYfc\ngi+vaeoL0Ov5ENI49hUHMD9yx5kCOOAQKsGQMzq8TGIO5e9Mj/LBg6isUtqL\nBTb1ycfm1LUWHxg/q8MOmM6yYF9R8u4yIwUh3fCxS+ai+UaKDTGPm8SBLC8D\nkJV7\r\n=+Ddk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDrKNDMy9WMnyDF43UXaqzNmXj5bYwqvqQEO+QnV7CnEAiEAnbshecoPjcZyEMqGZ+130wLEQibIdAeLYnhFVJWDtHI="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.0_1627398472360_0.953679368640092"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.1-rc.1":{"name":"ipfs-grpc-server","version":"0.4.1-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.1-rc.1+5c43562d","ipfs-grpc-protocol":"^0.3.1-rc.45+5c43562d","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.1-rc.1+5c43562d","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"5c43562dd3ba2d2325e297e0a42ef441f9fd2615","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.1-rc.1","_nodeVersion":"14.17.3","_npmVersion":"lerna/3.22.1/node@v14.17.3+x64 (linux)","dist":{"integrity":"sha512-xyo1hKODrbpLwBpOv4ZWWXWN5QPQ+bOigQuZj5x65Lz3AsusTYBqgMLuea/EQtttF+tt1LZWBIvnw2TwnGicmQ==","shasum":"a5f3bc57590b608fde15a0d3d343aa3e4c76fd71","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.1-rc.1.tgz","fileCount":31,"unpackedSize":37842,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhAT/FCRA9TVsSAnZWagAASfwP/jlF0VBFCxIcQt0IVAqR\n9kcyeD1nwvMlJgXZ8iH3ObLm4nExhPg9SJ4lV63ngCKtKCwOeTkzLZliwC9g\nyt9NiSg5hxZDTXeIsAJ2uusvn3RHIz9HkgAOeWml1UUv/SsGzeBeAqEEVTON\ngKu8HdiCn6QK3YUmH9ed30HZzgJ4lclLSD5bEb9r9GVB0m57H5oovau6nVXk\nkAN7TmIrIIDRL1viekxBpExyGy4EVopIwdtbNQCtBUyYnD/lW69S5fDiueUq\n4T3T0DY9S/vVHskWWuPreak4+l/DAW+oM4+fKx/d3mBeyR/FDXc4OKrhfO+8\nqH+Ew/K4CwNuKLjpdEfjh9KmOyYKgd8RI82d+1VDc1Ggxww8zL+XJcJLncN5\nsH6t57DWk2Uuupl7o8mLJ4xWU5gK6iHNMZFWyt8xvYVASeTM94F+ijTBUX0x\nYPJQAHwrSZPz7SMPTc3NxP65vBUXGbnnI2AF4Qaj4ju8LwvVyllSo3mrXaYp\ngPyPDUa96OF/C1s4tmVshoqDl1K2ZCKtR8W97q9NauqUlwnZJpV1MZnHHujk\nkwL5TpwApp2sVOUIDrGxrQiGs6KixLJbtBKJZXzyNWqewobHC0nM4BH4Q52C\nO5TLmMIcSfbGJhIsyIOeKaepR15pSU4HFOp4DGXNgnEj8oBRW+/c3PESOJDT\njAUG\r\n=frAb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGe+X5KuO4q6bsL9O505kQlgAfJE6Qp7Reio451YbVDoAiEAj5RnoyOGzKJgY9zdi+ZiF1ahN4JfTPfosJo3VwpQQXE="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.1-rc.1_1627471813268_0.3652702977346134"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.1-rc.2":{"name":"ipfs-grpc-server","version":"0.4.1-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.1-rc.2+fa015c9b","ipfs-grpc-protocol":"^0.3.1-rc.46+fa015c9b","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.1-rc.2+fa015c9b","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"fa015c9b2291c375a5ecd86337831eb1071932e8","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.1-rc.2","_nodeVersion":"14.17.3","_npmVersion":"lerna/3.22.1/node@v14.17.3+x64 (linux)","dist":{"integrity":"sha512-WaP/D1GCZoma7iK/3sGPGK5dRyarI7KWgx8oczX0zZ94XwKq3Jtycxwsu3XvxDAW37OT1RCEC6MqbeFarDQmTg==","shasum":"4ee7d8f189659b0124750067e95e029445804016","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.1-rc.2.tgz","fileCount":31,"unpackedSize":37842,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhAUy9CRA9TVsSAnZWagAAMJ0P/3amgUxWaRdmNPJeM6L0\n9PXfzkymyXc6fzCZX0MceMO+ELM5ng417yo0wWtDUkc8Yz8Zk3RgkofbZM4Q\ngXob+Mu94VXfsKfSS5jy0eylhmMOG58MumhURe51/Q5aJnhzDVT7ubpgSaad\nSdzJLwVrK0JCL3JkTvC4UyuOSZ+UOLZKunde2aI4dIV3f3eS8497rvGYD2lp\nJO79UwLRKymfR2zkI54sqAOqzUjNnWeJWMjV5I1JTeF5SQy09lo6epj1RatR\ng2AnmH4R36RIxBUIYkww4QvpFmJFHQN9Z8cRz+30ZEVMTUEnfb/idKzoV4bW\n2F601s/UukDI5x4Gf8kqc4nCqR/UCXHgEsPY4Df5XdyQooQLLFGlsOsNeCQ7\ni8ZYJr3jn3A5J02LsMaKhU691vlQXDewPeyzT6e6hgGFCR4bbLCIvypGeD+c\nkzIKX0597SRP5RRmGi+vSjqf7kv1BEtHwaIleKPsmG1eVXU/ukGp/sLt4miT\neprGrKjIE9sm/yElUBjAolLODgnW+kG8VDH3VVzX6+r6oAwatFYPjR6jLPbI\nHah+5UE/Mi+buATqYu0RbtiYHlceP88A98WSJ0mDE4BmHAVObgPxFhqv7AZ+\nOcAE5Ks6qe+RKq9Z8f4FwdZSoQXsOJRCfUwN5lJiZYUMmPUm6Qa+7f48JWfk\nhVeP\r\n=0q++\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGxFr6R8/a+dUXRfvfbaRJaYvjVA8kNwHsN596cn43VGAiEAqTZ23+K56Hh7NQ4muvVnmHwAtdq+9lkKNPfmZVLEv18="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.1-rc.2_1627475133201_0.3729397762594846"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.1-rc.5":{"name":"ipfs-grpc-server","version":"0.4.1-rc.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.1-rc.5+43db72b8","ipfs-grpc-protocol":"^0.3.1-rc.49+43db72b8","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.1-rc.5+43db72b8","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"43db72b87f0153ae4e9c46aada750fbb85d0bac9","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.1-rc.5","_nodeVersion":"14.17.3","_npmVersion":"lerna/3.22.1/node@v14.17.3+x64 (linux)","dist":{"integrity":"sha512-YuVZ9Sac7eMXA/LKe6apL9BKs48ZRERaz1e4AN0AYyvmhvH2BJh1UC4e6O/4exR8FKSUdK447nTbjjkaXKIb+w==","shasum":"ec2c47a371ac9a0d4701b0e917442a99acee24ca","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.1-rc.5.tgz","fileCount":31,"unpackedSize":37842,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhAYxNCRA9TVsSAnZWagAAmSUP/iXeYZ3r8UBbgfXpV2O6\nwV6h1+HnfX2+iOjc0H4TtEj7TjvwEZn8A/3rzylqVwZDrgf5oWn9Tpx7/2F6\nN/d2ff8u3+IhGiJOOOAFcraMKEJ2iSYQYrtPUoYI2YeDUu8WCv+lsQehCtaN\nBudJ8hNAkXW6QJWgHrJgxVwsnGzWsKaJS/alR6112JHcSOcPTaLw2LgEvL7h\njpzJ2Y4QQvhpaT17G4JU25trWXQQygjS4ml9VDDp3b5G3c37pGGpBDEQGye6\n/67VqdhNaPjtt5tJL+k1W55KLqmS49Cq8YtdjzuWGLxGWoEG1fxeApb99sQt\nCRgx1znq7H2efxAQoQ5AmboE1OfzUOnyiDhcOmZHyh+Gvc1sqQClhu5SdeS7\nElVsOAPH+sEP+MqFTTORIdE65UJeehtbyNTyCDin3IvaL0tpDyKh5zn0Q/Cv\npxg15csNQaTHwsXBsl336kIv0pFjjfiUSo37sLvi2rwMj5+n381ukwN+bWBK\nPrUQPm+/sAm1XJTdtUBXqV5wHEZwOmFyxGYN6Zi878Feoxwe4Ls0t0ttfujv\nxIOXno8krt0C6hWAxDK9jBbdJykbsLNuJK8Va6z/tgrZULzrct56tiiiUpz8\nh3lHCLXARNFp2g4k6kcQQLx+QN7/I64UaXPh3YFvybf9Po5Lac9tGIWAeZ3K\nV2/m\r\n=3VDm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCbVGYoUsoliXMFoI+cUxY+9nSFyHV8p3dNq2deDlyjYAIgeQfkoszUqKouFwVZl//h5BBhKGu1qCEKJLEehJbnkhY="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.1-rc.5_1627491405467_0.06347489308354715"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.1":{"name":"ipfs-grpc-server","version":"0.4.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.1","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"dde3d28b4a0d0f74d73c0c0b38eda2e01874a2ed","_id":"ipfs-grpc-server@0.4.1","_nodeVersion":"14.16.0","_npmVersion":"lerna/3.22.1/node@v14.16.0+x64 (darwin)","dist":{"integrity":"sha512-VbEO9coByAnDuOZoPh9HXSuGuB1IP+Jp8BAdOfz0/eGoAm4GPDu2zznGnfKS9TQcdXRPJkbx2sFsdzcZ3lYCRw==","shasum":"85c222399ecc83691d0d143be7c4185a40f258f7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.1.tgz","fileCount":31,"unpackedSize":37961,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhBDIKCRA9TVsSAnZWagAA1VgP/2WAXnX5ywLrKdf+WN4m\n3O4Doo/OruP7PRTcsQNHBG/c6nS5vEB6hDk+ZGxAciD3XQT4YbtO7Ik58BDX\nMoBicNac37St9ciQUfK05wRRFAkagoDdU7T15/pjSxVkI5ldHTk/p/29NNZd\nmzNZIuL7x/NqW5MCTkqW8I7P/fYknlfyM1SU5GTjhI8dSfZLfJ/W1lwE11wi\nFfwpqFzwxiUHBUFJWTkXfCuL88saetSBINNzLedACjMNis3I8Ezl222icO0V\nVcvEHHd5okv7FWUiKmLI1z6ECuwza91H8v99rUYebryTstH40hd3Kk3e9uaR\n31rBhWB2HQogLJqPj/BacPavtAhSIxzHAQrrOz5TFZJQ6FeDcZhAVHHJWHYq\nzMIFPg+j3IEmAoLkDno3oFgt5BGJ1w9ao7bp3rk1hDNJi8cC7U4/wCqMn8DY\nZ+9cko+AtONrP66px2UViV7ZnxXqJTdiO+rkxzfCPApm1fGscy91csu6B7d8\nXRVDDEWN2VWD2jKWtc/pszyyUIOFt8ufMu7SmRCKpTmJTd4xOYh0lkJQfOTE\ncT9FygPjipkUDU4Pkh5BEMRY91O0K0qo29vO7/r87n5FjGDeG/Oxos5hTxNa\nvemp1HcT+VWJRklOHLRReUhoAOq7D2sCysC1CBfCdtCa5jRPX1qrxPYVNL9Z\nFHnR\r\n=Zz1H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCh8BzQQks7CNkF4Op1qb678eOnWkR+lxVZHCkubAu7ewIgQEyTW+wua6npyZ8T8Ly5uS85d6aaVpvkoyjYHY2UjYo="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.1_1627664906593_0.2531992278563042"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.1-rc.7":{"name":"ipfs-grpc-server","version":"0.4.1-rc.7","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.1-rc.7+fa78b4fe","ipfs-grpc-protocol":"^0.3.1-rc.51+fa78b4fe","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.1-rc.7+fa78b4fe","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"fa78b4fe1386a151422bbccf33818f3b15fa36de","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.1-rc.7","_nodeVersion":"14.17.4","_npmVersion":"lerna/3.22.1/node@v14.17.4+x64 (linux)","dist":{"integrity":"sha512-Z1+VK+CYji9GOX/ssdQv/ABwS/jaHXn7xyW3FlBwCo7ncSHXh6RWGxIH13x7qOf7jn2gWCI7xj/96UhVZr+oUg==","shasum":"88bc4feb1600c9a280c643ef7df3610d895c4226","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.1-rc.7.tgz","fileCount":31,"unpackedSize":37842,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhBDdTCRA9TVsSAnZWagAAK0IP/RzzN1f/wAYTG1jt5w5x\n0i39u/FtEIiBFO6n140+TbCFSicrt+DgwY+ZChWVWr7a3MMQIJJ47KXrPg4r\nGaMrtmZv83IWiy3hknLdNJHZb/41fXq1AcVxN7E7AM3flmc3Oei7tmMaWtRQ\nKxezM2cipbKwhipjw+YRddOoTD37Dqiqkh0dkYK0hAb564re3C8spsCZwncA\nxasBRAs4Fgo12S/i/q1zB9tDI7LSQriKcinKLQfngJ6FBifSGlpEGEawnWoj\nCu1gck8C7ZyizC4urGXpNiGxUdk2MZh3fGKjGyyPMFlG/lMqP27mErr8CvRW\nn/XCHptqs7fxmnS3YXXlAOSQrqIyAvgwwG3G7xns3LJcbfLdejLjvfeiRUjx\nYJrSXUSSAxiG0CY8tliJ7mkQ9YgQ/cldfbceZOcDSDgd0SVhdtl8VFtakce/\n4XS7QFO+IFl8OFqPXGYbiIVpRmjf2KqplYqYWKzmAk2Ug4jtz2V0hzY0Vmqc\nB3zZzkHobZdObUy+p885ftAlXrM99u09vJxV/b17lH2R2l4dvaSd8xFFY8RW\noMJ7JPaQtnUOGuTyqzPuxknW8UFFwfvOJWQ/pG4/yVegCk35sacnUmGjksCW\nqeemB3QiOgmpT43CUAs3U9lgRIKeJYPoEEJ0Wv7nBlBrpoI0GCC6ep0ww4i+\n4mEb\r\n=QFXk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCtt1T0QIcgqlYCOXRDn+BCvBJDr8AEtIOpz7FAU6m9cAIhAM7lkDx8T1bT9XN4nrTKlc7cXt2qQi2Mo5co5/FKX1gl"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.1-rc.7_1627666259613_0.08741235265221436"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.2-rc.1":{"name":"ipfs-grpc-server","version":"0.4.2-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.2-rc.1+48f655ad","ipfs-grpc-protocol":"^0.3.1-rc.54+48f655ad","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.2-rc.1+48f655ad","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"48f655ad4a2ec96f84c4f73082919a753523408b","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.2-rc.1","_nodeVersion":"14.17.4","_npmVersion":"lerna/3.22.1/node@v14.17.4+x64 (linux)","dist":{"integrity":"sha512-ggmJXglhJ6wMu0QGIumkhTNaipzxzTZPPDTeO3aj7ql8d5AaR2fOTyITcek2YN3f8uLatLpz0BH77WKPHOntYQ==","shasum":"fd797a18bc56a3c0898724b58079b8af15c5d935","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.2-rc.1.tgz","fileCount":31,"unpackedSize":38018,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhBEuRCRA9TVsSAnZWagAAHzQP/0ntfuW0WeootZMcpEbJ\nL01v6D5vafkNgyx89buQaCl0l13x93K5oxHIUIrRhdzc+PJGd4VkhIPabeZB\nVZZ3J0QuuqIkHDVWgkxaisGF69sBLjh0esuQduExwLol+na8mn3wx9FEfNkQ\nm9DTa5NydRxFTi3PlYfyRbns2CydsCtAtxlKN0dfyeBwAnd0uPfWswRe3qDa\n9cCmCclwuwGEgqEupNYxtKNAvMR6VMMwzz6TcWiPmofrBvYyQE4sm4GpIxgZ\nsn+D9EH1kxZLeJrb7sWx5vxfm+YWLxTfvvodXTVC/5azzmg72wxe3JcDhfrD\n8c217yMC8fRBE7Qoq02Mklb62maiL7AL37UanOJ51UfPS9AThkqNFLt8uG5+\ngZ4mvMSl29FmrDz5gsyozBtfqjDGJ82eEpVl7ugmzuenKnonUoQzznyM6CHf\nVUoGGerQtmBDzwasmv5unCRTA16nQ2MVVuDaWqGQ0nDCq7x+Qk/IkzaMxlI5\n8IzvNqgFVmwVYrUhxkx6m9vkEB4cJA/CkOFbw5ID//yMVRhR49G7WNTWcasf\nCoSuYJwaEe28hortlW9uxZW22RqBdxkQLsddJhKXqkq56GxvpC4ONA/usisu\nWSYm7t/z+y1RCbvdAR0ZVEyb6ewlygxKZRljCsf4rS+C0n45j2ey2jFvskez\n2hhi\r\n=CWL3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDOdv9dmf87JE1Z/vPiinJYSKrWPMag8ph2m1yMI0rC1AIhAO9OJZ6mfHkiJqcH8k819HWN7Gm6jWPfAX3rnyhBSohq"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.2-rc.1_1627671441168_0.2537934603755494"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.2-rc.2":{"name":"ipfs-grpc-server","version":"0.4.2-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.2-rc.2+1db6b88a","ipfs-grpc-protocol":"^0.3.1-rc.55+1db6b88a","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.2-rc.2+1db6b88a","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"1db6b88afc5647d3a187e0ca4199d8ab2082c629","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.2-rc.2","_nodeVersion":"14.17.4","_npmVersion":"lerna/3.22.1/node@v14.17.4+x64 (linux)","dist":{"integrity":"sha512-BN1Yj0Cl037SEWy1moAzjAmHfjZ3IEhyY56KzmnZc02mnd3NynB4dBGaNdD88HhjjvErOS17xInlahTZNjyWCg==","shasum":"27934ec09800cf9ea38ae128d90e4d81e82a9a29","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.2-rc.2.tgz","fileCount":31,"unpackedSize":38018,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhCpuvCRA9TVsSAnZWagAA7vYQAJARPB33YzwltZyDhOV+\n/bcq5T9u8uqnuL5p82bG4Rt0Gzy7QiC5ehUPM1NtChBM4ftm5OgCamUWvmyK\n6+aKG0GJATQxqlug9aQ49PKJWpwAMAE/Dj6AGtvx3uSwtD1oACk/ZYeMuULt\nfNH6L7OXWWJtrLxEYL4NYPBdHytkWKuT2qkB8S70QKbY0KjxLlg+HC0lAwwl\na1Mhia1ujs4jNBAhcrWsrXO4to28CPoL0QLoKYknXKW9nEe7TFNO7cWphS0J\n6sbzh0Y7eUj+69GPNij31cXkVtdt1WRo3GjwGvyXaNxnD02DRNPn9/Pm3FdO\nMC7jIQFsdc9EAv/vHr3tUraBW7B2co1qLNhnz2XwVWbLUWn3Ze3ZRXrFZqwg\nluJOV0L6BgiwmM/vnXlgFPX4rSGhFb3w1tmhKW2a6P/2uYYOP0Rtuy24aC7I\nJ23g8VIskhf6tHyrNVBgIQcy7aUu9QpOjmZ+cX4TpW5DlGHrm3dM5SKok+eV\nPd6EylmoXKhc/S+b5iPYp+4/52N2Q0N99ifvJOIoBLckg71YpBfTv7QOUCDU\n8CCKND5mglmC5PY+iRNFtwSTWDa+JCnAoVHp8gSwLvSgDDRq68CkiFZ6hgtU\nUxwemY0VI9IMyU72OV0t8OSmfVh3+MlXnkZXyBkjSYDa33ZAzWVNA/qSqABi\nqvm6\r\n=9qOu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIACoFPD2w1/WfKZZ66s//CMaeiIUyKt4aNU9sRcSBAQ1AiBNjBB5heA3CFJ0/xYBANWDji7EjmOhXvnRoRWgDKCr2A=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.2-rc.2_1628085167625_0.4589161628252485"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.2-rc.3":{"name":"ipfs-grpc-server","version":"0.4.2-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.2-rc.3+6adc3fa1","ipfs-grpc-protocol":"^0.3.1-rc.56+6adc3fa1","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.2-rc.3+6adc3fa1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"6adc3fa18f1dedea22babce41d24d7435e497ecc","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.2-rc.3","_nodeVersion":"14.17.4","_npmVersion":"lerna/3.22.1/node@v14.17.4+x64 (linux)","dist":{"integrity":"sha512-m823p1/4xjKa4zUwJZCUZjwQs96X/OkAsjUlrb+VZMf9QT5VGOPvN+UcUbkR5cR8FljaPrwiqM4lqHTfbqsNDA==","shasum":"29985dd0408995178d9ec07578b73065f4e05c62","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.2-rc.3.tgz","fileCount":31,"unpackedSize":38018,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhC8//CRA9TVsSAnZWagAAvWEP/i+pL1QCQnSuXGlLhtQT\n3yut8SPMUPm8hKcxRlNyrLegy0D5ofoOcYtRfgOdueVSW09f0mp+ysXAcM5l\nbrpW6bqNuIr4hdqzSztgtICbpQeFWsegQ6YgiUTMPQd/g1+J9qewwHVdWjV3\nWu6UmFpmT1pqPcw3Wfdmq8jxYThsm/pYjvjHQo4jsuHnQMyzpXJQE2SsH3zq\ngqqu3TrqZjgZOLRKozj+cHKdtTCpJnuCKktxurjOmPNZ2TSE9hzdwPptE/Xx\naSCPQL2y8e0QtUnKCIo0Km/wQwKXDqsKZZ6Gxk1YzWA3a2nkysMk2dfzZRnD\nanwEG6BhnBFAhpKufc9hsjyazrIFvE0WSH+1TATD0ZctBtuCmw6zjkq8IpnG\nhBkI72n6QfH2FXPPELxcVeLCrYDr5g7nooFuhE3MGyVKnSEnAz5g6yJ9IaQQ\nL0dSqBjML4zqjhxpoGKeCdT3O7lTib7pPtp0fdgBFzjKpeXT4mXr8pMaGnbE\n64rAozzftGFVkIbum9a2ni+rEqOSowR2F+iyAUAHZsvQngYkaya8w1yPfzTm\n0QuHcLhdBTSof+2qw9syjA63Y2h9YakuGKYWHA9odGe0sWGgZdRxUVMpIQgT\n5sSmvwVxfrJaPZSvolKnvIAzsYLAxJ6EaGXCoKLAunSFtbp8gBoazbRbJZy2\nrDcy\r\n=sKhu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGkPUFGhoiO2IjTlTKD2R3POPrbEJKK/rrtdN4M5sTQFAiACiZGsh0NbinsNH9CnxKXdFqdx5QKJmeuM4Ct7VrTBJw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.2-rc.3_1628164095768_0.7624662087548317"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.2-rc.6":{"name":"ipfs-grpc-server","version":"0.4.2-rc.6","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.2-rc.6+a6c68803","ipfs-grpc-protocol":"^0.3.1-rc.59+a6c68803","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.2-rc.6+a6c68803","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"a6c68803ca19536c022c72554af2311962b2a063","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.2-rc.6","_nodeVersion":"14.17.4","_npmVersion":"lerna/3.22.1/node@v14.17.4+x64 (linux)","dist":{"integrity":"sha512-MhEEezGxvq4Vfi4J4b6ev2JDlSLPn5ymhJ3huUiy1mmeTIWkp4y/p9ygOXyQfneE9lexiQEjqo5SvUigWLx45g==","shasum":"0b54da213b96103d444c4ba3b46181aee643e1cf","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.2-rc.6.tgz","fileCount":31,"unpackedSize":38039,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhEVieCRA9TVsSAnZWagAARkAP/i1GZ9SFeqhlv4G9QMMZ\n60MhJGB9JbuCiMLfIQ/Pti48eSZclA2DEaghVYXwfqthUYktDPyxPT6AmD8t\nxcv68LCb1S8K0zWhPEEZsoswJLrraBbzn15YIaGqZ2SEApU77B99ZBJF0xaT\nzBRZt71vQyLBUSXo7NikdMUti3NtbY9R1sbL2zNE4Q4RCIzAHpaqC6XX2ErI\nX7z0lcqLHfE9lyT4JKciTiqDmDApwbJd1qBHFtYRoxBGSzzocEt0LqELxvCb\n7z6D48hIgvCDXYjdeONEo4Puzxhi5dDem44XRNjs4Y/Sbzg+8Do+KG8i+Hie\nqUeCWfy0h2edy/pE2L7wBJIbKUnrbCqGK4/h73Y9gKwCrgbwB7lcuNlDFmvh\nw961xbjG029R0DvwOPPjSB/QqbA2awk+YknQC9YV2Q3vhyP8ReNeDOahNnIh\nB816UGNEW7V+6naBRnZwLYy6zKgclOFjrqWds75FxU8AbelJBALfVsAdGTGq\nRvqYU+ZCig0CxBz4daJZ8jCnKO3zbAqsHZfQaWaecxu1qtCq+1KMGi/sqdwk\nPSzEsujf+ibLx2jWV47/kvanS2zSJGHc7ihiSEXOm0/ZBhkX/OtgdwSqSKgV\nHo9yDSWAXsHP4NMr9lQR8sTQaMozN8/TUi9A1SVTt6PWdCD9sIZLHhbC6ifQ\ndWEo\r\n=5m2V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCRq+7iQQ6zAaWwz9cGuFhpSKCuDURHxCTX/uiJJu3+tQIhALA1v2i1d6iZsW/VMSOd/EpgjDvr0L5kW95iVw0Oj8gA"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.2-rc.6_1628526750201_0.7262622397158183"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.2-rc.8":{"name":"ipfs-grpc-server","version":"0.4.2-rc.8","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.2-rc.8+213f0b2d","ipfs-grpc-protocol":"^0.3.1-rc.61+213f0b2d","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.2-rc.8+213f0b2d","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"213f0b2df0e407dbb97ac2de9b82830da234fbb0","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.2-rc.8","_nodeVersion":"14.17.4","_npmVersion":"lerna/3.22.1/node@v14.17.4+x64 (linux)","dist":{"integrity":"sha512-Uxtk+T5Lj1yBa0nH9m7ZmqaN4jYwYvDYuHzvmBeYhPNbhVCx+GtcPnPM43UkQoal39+EAUoxuoeslWkYYJgp7w==","shasum":"1c68b5a84394a2fcf454292717decb13bb3df4db","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.2-rc.8.tgz","fileCount":31,"unpackedSize":38039,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhEiiBCRA9TVsSAnZWagAAVh8P/1aIPF9/729pcLvVe+Wm\nEOENcfVogbhkpG6tj//8YrpvmT7yWZq78cRo+gTRXTNKeMzhMr3vQeNd7k4l\nXZ5FID4ljeD9r/iomOmP13CV0fQ41iMGrHuE+uUaLdyoFlYZUKe2fgfwvmGg\nzxZHK3tyuKvLCfLlFeP1yD+T0ykdq0Z6XtWyAUIGwkqUhDFn2NjN0YRF9sGl\nZge1PS4hbeDR/hSFU/NaA8F98jIcJ2ta7E6szbTimaiIQ12IJ1rkX14xDU8z\nD9tz7vke3Gc8PYLBWBwQIRWR1BAeEIqAhiyKgc0oHHLYMZfpzmFQe/QK743U\ng7kh3NuZksOWO76e33zOG6vfSu81taecFzg7OpWb3p3JRFInS/FMRNxpqtCV\nESRyMsf718vhSfjeMhYDzEmscW1eP3Lvr0sdTUHAOjSo5XsigmEjMysr0yjm\ndaqmp1IyitW9Wf3xxinNZGbKwVR93P0Ttd3mN25k105aOWJKd3EtqPj1pvci\nWzYWSNo7VNojx9coJd7MRgMYcJDONB7UBDEHy3XKSrhM/tq2phj9I3U8CB++\ngadTJGo2TAeXw0kaKmR2Og1WyjspZo3UDDaQDweOKQ5ZJKgMctttlr+3kLiO\n2tjsD4M/u6hBYZyVtF6yfBNxJ+lsWjcSROYVSpi1TGnxRxyfn+WdBiplE5cO\nx1aU\r\n=lnSS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCmUNQd9U21p2ynreVOCs1usMEGm/yRYWyxLtpQyl4HUwIhAJop/lL0pPUmpm9zNhHl6rCTD9bNRL4Lx8utF8S3/Vcx"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.2-rc.8_1628579968742_0.6573041595337548"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.2-rc.10":{"name":"ipfs-grpc-server","version":"0.4.2-rc.10","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.2-rc.10+4150d1e7","ipfs-grpc-protocol":"^0.3.1-rc.63+4150d1e7","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.2-rc.10+4150d1e7","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"4150d1e736c15863ae7e354fd1f7d6d4e34e4452","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.2-rc.10","_nodeVersion":"14.17.4","_npmVersion":"lerna/3.22.1/node@v14.17.4+x64 (linux)","dist":{"integrity":"sha512-jMj3pNaX+CrNqYIpokH+Kpl7Eu0M26vCFQUYCQ7zp5nu/153sb7NiMIffHXG96sczCiJzVBBQLMBFwKC/eenOg==","shasum":"62b495bf9dad976ceab9ba18c5e8bdf51926b9ee","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.2-rc.10.tgz","fileCount":31,"unpackedSize":38042,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhEkJcCRA9TVsSAnZWagAAZHUP/3iUAWslJVXC8N7voDi7\nw7O32U4shLoWtn5EMqPUQVlVDV1GLZABypN07Kj5FuxeXLu15Uan4zLjtT2t\nnGhWcNZrduYIl7Xj/yJ8njPUYoEQrKj4RihjuM5X3HbaMcUQmRQhKZFspZC7\nLLCQ90HIthJ/jtzdIyf/yu+/G3+dOL/QhtO6VyUYIUHXMkbu1Wt+XVfZ/24S\n0kYWpacyYkZOqPA4ZtNlKItqpJlFwNlrpQoIj3qGzqHEeCd8aPSw7d4W6qkl\nexAJi2e+Y57fTL6qalXzosSb7oH7r9QFw/h+QTvL0UK6lu2VZZk5UA7eQi/w\nXqGYMa4jK8RkDmqI+2oU/AunJ+WQwWfeRq+dcfdPvswdcPgKhydr43kWQhP+\n+t2gY7QYkm5OwAi8iohp3r8yg/EiZ2xiBjL648iG8/rShsWycgFAO2QOX4NX\nlbSXHJPVqBnwYcOvOWnwamcAYJZlnR1S06rxGNd3yXffYrjXqoZwiOiijt2k\n8ShpiviTigHU7nU202xyuTjGtW+A9vBaChD2B01Yv9mHFYz7LsjDrkofIiOr\nZSXHXtclEn8AFdoW950b4lAvWUT/CjR9stArYLZaaADrHo0L31AbhQhekH1u\nqZgD9H9qbuBZQxpSmT0gh5Z2j2u4ZHtshSBacAElhS+4HFlKnX3cIAZKrv2n\ngWRD\r\n=qBfY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC6MfkwCCpXrqAK6Kk5/uz6BOmrwKtOzTR5HuPfadW1UAiEA+FON/m6qW9AnaY4/Yf5EdXYEOIngJp/R/goVIrIN310="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.2-rc.10_1628586588460_0.2924151749163517"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.2-rc.11":{"name":"ipfs-grpc-server","version":"0.4.2-rc.11","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.2-rc.11+fae59868","ipfs-grpc-protocol":"^0.3.1-rc.64+fae59868","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.2-rc.11+fae59868","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"fae598689a0b9a3bdcf80ac71c19b709294f2932","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.4.2-rc.11","_nodeVersion":"14.17.4","_npmVersion":"lerna/3.22.1/node@v14.17.4+x64 (linux)","dist":{"integrity":"sha512-lYsgEMVK1eszvNFz3E8SNxQJ7ajUrG/9KX2n4rxVYCtbMdq5unfNEELzk2eY9xIwCBFO45K/qqn9PwvVqG+t6g==","shasum":"0a05b3c5f4dc8b32e254b58f6139557aa29aafea","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.2-rc.11.tgz","fileCount":31,"unpackedSize":38042,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhE5bjCRA9TVsSAnZWagAAxaEP/2rrzmlgNrydADweHrYV\niUxREcR14f6YZptah+xvPUpopxEL61uVt6A3G/8veeps/rPT+J7jkYQnEI4q\nQ3EVKZccO/ANYNJBaZd8h0PerzW0chNuMDsGT1Dzv9/C0sYSpglD+MCoSRUY\n0kw+eLQTqsCzpIL6bRRE7P9YgH0PGePfDBw5M4vp9R6f+BiB3Xz4pf2jUUCP\nfp02QxYAQNmhiXspgzM/c50oPDD5+MmQTllAQsObb24oZ3RrtwEBLgna8pAJ\n8pPajoyKJ1iDarM0iJ4KQtt7J1wKwLce3xp1EmnnH4F1QY5rwpRAyVV7IqBk\nZOWxulRWxfHrrJfcUTugWfLqDKRU+wHXo1Binj6Q1bqk9WAYU8gMUb1bleuy\nEm57QXSeaMs5009ujU4MOz1PQ+GHsYwUE0B0WI1nfLle+BM+eYpO8alVEewG\n/8/qxOps4+4tLkrS37PxcI9bS5J8gRU3q/MjvDVTP2Q9wNko1Aj6IIPdaZPu\naFQVYLRJzVTNg6wRXQfSRSKwn47o7OJJGcYxUqFEkbhSfz3CZHcX5k7SGBgb\nc5sLLl1y/YcPsgQkoRpslWTVKTgLqjvnHvnqnx4O8SHL8I6iIeUUv+RZ5r3c\nd/Z7JTS2+/UjgnE4tcp+nOWpVchZD97Cm0rP0DVwmXS9grB7YnxFJA3iIvVs\n1ItS\r\n=uL/d\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAuWv3AjZmKFH8GP8QmVctoLsB0WnoqJO/jr0LCu6ZcFAiEAxaquvfEcU8HzPWwMbbsbRXYcxiNZonQyhvv1BEfuBZg="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.2-rc.11_1628673763524_0.3332750917211682"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.5.0":{"name":"ipfs-grpc-server","version":"0.5.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.0","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"7f241319856719f2d9f2c1fc4a6b1062ed1ad398","_id":"ipfs-grpc-server@0.5.0","_nodeVersion":"14.16.0","_npmVersion":"lerna/3.22.1/node@v14.16.0+x64 (darwin)","dist":{"integrity":"sha512-GedsLkJT57wBGGZbqu2kPL8nKz2evoimDVQ7FO4txG1i0ikFT1qiMaCDACIDawFUjavGBC20vFzRzN7qmgyqbQ==","shasum":"270393b74d0a1c1fa464d3c9235d19c86407ee4f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.5.0.tgz","fileCount":31,"unpackedSize":38461,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhE+isCRA9TVsSAnZWagAAijYP/32MXUZ50tTiSwGWIA+p\nzVP1bffxLndxmPAPCFjYDbKfpibQu1dU3ClqPd8Y2gmn5MA20pjc3DQcxyfd\nIePyQRyxCHjb5/gneX+1CPIULfRnHK2YWhaqapr/aczPsDStXWb+7cTCSVfI\nUobopNG0sxRPoANVHNC1dU1rPtx0Oxjk4MeSJ0ryMtQ0llGVTKKZpGEBto5H\nJLU8KlI2eIA4g+7+EAhb3h50m89SnALWK4mXTDH56BmSUPB++Aki1zPyKpsL\nmgh14TdAxQ37y8mTPYcKrea2zk7wJGPrQyhHSOFG9lruS4FQm8VPY7xwc42p\nQpM7Qt0Bz0nVfUqDJaTe5a3wRVqZSDAF/+/MvW4XBidS7j6ds28Tc45MKkvh\n7oIDNL2nSyeE76YqWORAX/1dgkl3dmsLfMCfSuBqqvbl5Gz8yFFd2MW3t/ly\nLvqn8W5tQA+uZ16xxtt+BvPgTFXHVqa7JRGsEyKcWXuDZrKveolvyPTWbDN7\nrhSAspXnmT63VuW1fdiQB4afmChFq3HrUZvFXo022x+HLYoXaa6Vmu/KVmyH\nsMcbG/uPTV5XKzeVDCpETfXk7VDQcawSg9BwPdZHVjlzoKAJLKOusDXn/NXg\n8p/uFB1Dw9GZcMTqbxS6xyXAbdE2107rben+ZsaAzJ2+hgF3OxcYrp+1iFhf\njA3A\r\n=ElKZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDGgV4kVQTxQKFTLeNpS4rmGqvlWAkEa0vuncaNBSprsAiEAjJNWL/D/LYiA9WqpLl3eaLy1SJsK+JKKYMjjXj7ajAU="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.5.0_1628694700503_0.7213062145259483"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.5.1-rc.4":{"name":"ipfs-grpc-server","version":"0.5.1-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.4+b7735674","ipfs-grpc-protocol":"^0.3.1-rc.71+b7735674","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.1-rc.4+b7735674","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"b77356741ac597f57e0b9ed57cddcf0ce3fe7806","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.5.1-rc.4","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-5f2wtr+0V+b/vYiah0kK2ERhF6Lg+wAs+gmdTIrs80xT8ShvSvyQ9uwQguyxdW8mVXBF+kMiCGC74Y1fwuX00A==","shasum":"84dd83e3e24d3dc49583d3a088532af45956b240","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.5.1-rc.4.tgz","fileCount":31,"unpackedSize":38518,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhFP0SCRA9TVsSAnZWagAAtNoP/RYvqCQjd7/git12wOco\nc1kndcRFeS6FK0mg64cpSxaz2b9u91XggSr2+6uG+kXWVXjcLjidAjMfFiaQ\nSGCrbf3JmJwzqX/3VkWy96AMsuPBCWmwEFo9+9Rf9mVofme0SA53R3bqs8Sp\nVyUseziwK3/d97bz5wFczz/2xxXa7StJQbpkxtYCd3MLrGYxsZ1qFQCemPOr\nOLj+qcFSrz1mT5dMfpHTSCOF7NEMnru/C/VSd2Ua8s9m5hy85/G2uCq45Xqi\nlZUrBrs0h5b9bSNg5hXUhg/jtxrXkJEtuxZhw80SGSR5Ze4fLYnQzZc7sWLe\nn+3cWjPoN94t7Hv6eZWpkQO11MhMTY7ljsv2ca2R5bUKMOpGG4QFfcIGmd05\nROuAAeGlK41KkEKKncMU0dlgOx1mRbrz+31tyHWThdhQkmTYcGMHe5QPxPBx\nKbAfqHVkWqLEV0W7DnMoJlEBjp3FTJ4/fmLvMh1xFGOvCVpufEFbEU8pbw+0\nzCM8VtYRz2BlDpfG7h3+lCxzGyBmLQN0dIvz9ELpxqeFjsnx4If6ZKNFr13b\nJJB+erFTo3SeDCT22aXsGD47TBwU6P2R4TkHaIplik1fLztNBU3DiJcpCgRc\ncFPXIiFRGHuBPN1qcPVlZUtiGuftvr7V7tLp0I1+qzKg/nD8oTSTSZ+EfgEv\nQyR5\r\n=Hp4a\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCRbz9o48LaKumVxtMFYLz5UHFqwIf1CZfDHMl58zDWQQIhAK622sZ/vXavAU0pll9pZaLGK3oeUHgHRlhVUM+LzlOZ"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.5.1-rc.4_1628765458120_0.5799395665165006"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.5.1-rc.5":{"name":"ipfs-grpc-server","version":"0.5.1-rc.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.5+55dfd937","ipfs-grpc-protocol":"^0.3.1-rc.72+55dfd937","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.1-rc.5+55dfd937","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"55dfd937e4175e049287b9093ed9a52bcf085711","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.5.1-rc.5","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-4AqSDQctfJ34cchEvPQpN/y92hR8zNdIsdpFA9RGl9ZGhYz17WhiehC+yyuBbj3j//g/Z/Haa4oYBAWalzwOAA==","shasum":"0d2e60ae1ca92bd0efe81c8a991c60026e692f77","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.5.1-rc.5.tgz","fileCount":31,"unpackedSize":38518,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhFQDjCRA9TVsSAnZWagAAV4oQAIv1pa7T3DWLll/Hdp7K\njgE5QVSawz2oU4kZnle76XMsdrqiq37EYHVAfsuc0D5g0LeTcEkazVZNOG6e\nQXu22e2Cj45l2rqXQKFslyRgKy+FEd+Tq5XlFBSZr4+FULq341J7XcMC+7+D\nSd4akyLgT3LPEIEgn3HY29FZ9SCpFNsro3MB35ykCHtEMZLjU+4VrNFKHMeo\npdWmJnT8MRyEaItTqAxK33Y6a12Xwpv9za+94/dsB91TqjWYD7F20vSCN4gI\n8/hnwcCfQKAMKptqmq95LUGnjlJH+0fw4pab8CeELRPE5q5EjR3yxAd4/JRJ\nea62/Wk5OCKdv3Wr5o+z8PbD0pSxIcBdI5BEOCtiunjsq8tb3/A3UUTa2WUm\n92s+zk7J3zIv/6ocCGCVJ8RuYGroEiAx+nufVdPK73V+IJBm6k9pXYs3lqpC\n6avy/O2g43pIaNU26q1Dz32tUIqytbESa+ZZs0VZzzuFBbHdqBYWboRcYpM0\nKUfA33hqAH8ww2OqGyf8t4+ejtcHlZDhr/e3AaM2bAu2ix5f3SCTGCi0YQYA\nCN8pYd73X0Zv+R7PyezWUNqNT6PlagRwa0ol4POzddpSbPNRBNYD/OVPtSyB\n9opxvewQ//4YI8IJeUQp70IMjXDCDdGUM6TAf+GX46io9k4bnM+hUy31JJvt\nkfve\r\n=yQaD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICYWaZ5vtH7FyoAsoLnVTyaa5seyqEbUqupwCGacx+q2AiEAwdJutWV+2LrslYc3J4qd9okxXjiQxXOdGtPQO5s8R4E="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.5.1-rc.5_1628766434872_0.3423314361562626"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.5.1-rc.6":{"name":"ipfs-grpc-server","version":"0.5.1-rc.6","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.6+9eb29106","ipfs-grpc-protocol":"^0.3.1-rc.73+9eb29106","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.1-rc.6+9eb29106","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"9eb29106c07253d50121a5be1aaceaf62b022742","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.5.1-rc.6","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-ykTi8Y0K2QxqwxEk3qiWq4Lyqoxf59vQ8OU8IUORdyyBrmug8yMP4qpqP8WbHBIF+FWnZpwgF2sj+dOI6yln5Q==","shasum":"ba323693d3811df35dbd2c4c1a63d390f236ed7f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.5.1-rc.6.tgz","fileCount":31,"unpackedSize":38518,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhFSvrCRA9TVsSAnZWagAAB8wP/RL/usJP3CVIOZO8KI/H\nQDgDEKQRg9G9DZFxmpAu6WnJ1LLLVLZaO24hVTVznUszwNAvYAsyCYfCpPY6\ndoHzuIOF4RgoRu+je/wnL5BFoXa04e7UH+vA/hTTLe+oKHLveHX7InKWDzjG\n8Bs4OjL5XZa3VX3YvOXiZWBlXKqyPQas3zdA3MxwNE8rlGr99yIcFlvZ8YlR\nntQ/ZgA3XKQ4cUsABu4jy5pk1uss5brTv608QuGGUNMM3jcIyHdgt7mkj3Nn\nNKxGGpSmDBontvwh8vS3RrLWXfPOZy1RWC5y/2OWSUaqW0rakEYkfmVqIr3u\ne0hx3z9QHBoLslDBuOg0IHxg3CJ6xgPgE4aOcMRFFG2Do7PYeBpaOJk7qMBx\nubCFfBPY+Vvli+COJyRLVg2Dc/cx1swr9cdJAKMqTNHwM2SBi74lf5x46fVn\nPouIQIu3m/sT62CFLjPn4ck+SUhhkJowxK3+mg7MA8uj68tzMAUBKPUoj303\ncW/gEHutLvk6vWzvsRc4irVaoPG9u06bMQ0Gh9HNgZtloWCTsJCHTW9OzMvi\nGKO3zey82OJJO4arsW07tKO97/nZyp+VwqoffQLstsKxTxXawYuvQpx8I+6o\nfBuoeP8W8rRZ+tSSKyYyg68YeBvoU+YxLsB8Ic8NEtKJxTFV+AU0G2YvYvK8\nOBRE\r\n=ASZ9\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBzlrc0nbKMD2ajJwCHv81V4Rp0QKME9lVqt1HL5xgLxAiAlezWtY7BGrLPuQIcJ3UZC3m5AieVz+9sHd0Gtpoi7JQ=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.5.1-rc.6_1628777451737_0.7031796786029159"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.5.1-rc.7":{"name":"ipfs-grpc-server","version":"0.5.1-rc.7","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.7+1fa4e8d3","ipfs-grpc-protocol":"^0.3.1-rc.74+1fa4e8d3","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.1-rc.7+1fa4e8d3","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"1fa4e8d34f47d1d6273b6d82801d324dcbc6cb61","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.5.1-rc.7","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-0GhtTCyJL57Jp4LBj6t9+0n939uLrepkxYyLZ2DsNzQMTUO9cM7VjSeaydlyBsTCiHFyMCbnC/1nNke3lWGX2w==","shasum":"5bdcac68bb580fd906254387db5deacaa56f311b","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.5.1-rc.7.tgz","fileCount":40,"unpackedSize":42994,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhGoiFCRA9TVsSAnZWagAAy4oP/AnWqoKf9Qj6sYQmysii\nLCxpLJ7lpFE+SFmNL329BnsbIWw3dkKSZFj/Wk0yu66Duu2odtSPwwNQndMZ\noTAsQaQJp0q0swBYTIpvx7JRe7uPa2tcLJNKrbx9QYDxj3i68wmdnrfuCVzM\nNpLkIqo0MLel/C7BuQ8qDCwaythCQasumRY8Yq9ECb/KCxtyl/W5bdf5a4MI\nnqRFm6zd/ygJ0qfTcVksLtnBnzNEyywuG/WUEagSGzPS0MuxAtReVoN5rIKP\nt5fgZfD9uck3nY6SGm8ezmC/ez6/WeG7z5xF/o34+uA6PAqCd1eZOFNBAdVn\n+zvq6pnq8urqfbPszRnyR3IJASYYkbuqKjj7uwVDJ/+V5Ymcs1T6JodAsg2H\n5h8cDwU22y0clrpGHo++h5Z0sV0zw47Yn5WTiIDM42KsSZqNP30jO9DOkWDn\nDR3boti/OSFOV+2x4Aji9FQJIw6/pD3bK1DVwYlLjlYijqKakNjxy/Ap6pm0\noB2J8yydq1qcc60hX7vHF4pC8hYBINpDFjZogx7961nl1za0n/gTdrcLrDiy\nF24qZkrBMIVW00tgn7TcuvZBOtS7C6RvhjUGWGbPL9PTnIgmuF+eKGxC7gTX\nk6a4RstecfLsEiLvUUnAcp64fnokffYa3gjj0Fi/Deb0xiu0CrjMT9nrRl1Y\n3dOa\r\n=5hmp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDe7aOgvCREcovyvzbT2NcpG1N68ZxPaI3P0S8HGTaHowIgfqoQ6UipkL//CVo4Ld75l0ly/QgHnrEAbK40vTVjWgs="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.5.1-rc.7_1629128837490_0.8210602037836259"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.0":{"name":"ipfs-grpc-server","version":"0.6.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.0","ipfs-grpc-protocol":"^0.4.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"f9099fd0b24c0f474f5a9a3309c16adad5574b83","_id":"ipfs-grpc-server@0.6.0","_nodeVersion":"16.6.1","_npmVersion":"lerna/3.22.1/node@v16.6.1+x64 (darwin)","dist":{"integrity":"sha512-N5fsyD8tsoM5O4xVsU0CRF2uUILaOhryRj0stT0ZraSeQOCUbSbdDKLRqyoinjV1NyiB4pyFy0S5mJyU6MxU1g==","shasum":"af93af6d7fe205a2b0157ebd426e6993b1f28051","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.0.tgz","fileCount":40,"unpackedSize":43298,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhG5KcCRA9TVsSAnZWagAAkJoP/iL/80WfbAzeeN/bgqHR\n+W0YV8kbqafzSDxcp19+d1Dq5Mk0RyoruJchYHm3UfFgQaquv7QrXlCzhuOn\nnJJtbQrqdpgR1GkcubAvt/rTlCcj/dXNppm8zHlF9XuOZLW2P4/vZhg4JWhc\njExPXOeoqKYSCaDUCyIx+9lISelNOM1t0AabvrHMuJ+3ujd6RyHU/6vzwgUC\nq/gopFt1OopKzHw24zGJbJ8v3Q6hm/9ORmGN+P99T1auGx/cRNozusTqCzn9\nPoZctGpJIS1tVt6NWBL5bEFYTw/Dt+wZuNeW/Cd0RW3soH2PTpq3Zp9YpSoU\nfc96G7hwFPe3QVofsIYijqUKLuZ2DF9g4z5nmu5Io4gGnRROQrnqejAu9y1W\nzovG75RfCV5QueBF4Oc7pHwJ5Pe3LI4zICgWQkE0ikw6Tc9zLGqy1Kd7wRZA\nn53JlKqc6TgIGfUmePX3HI3ur8KQ/DegXlqarOwwFgnDeQLGK35NF3W79N0N\nUKUMlFTqL4S+++CpvBSxeFrkEti2xqZ/zcXyfbpeGFcQPbkxlneYNQBYrFzf\nGYJzMRrKQ9zXp1aGzlyP4Q+KWtCQTjSF/gYg3tZV//7cOO0tJePfswtL/Ge0\nThIRAbAPWlaaKYJRbKxBr0whmNRFg1KktkeG82VlovVD9OalyBVEitlt2BvL\n1Gao\r\n=fDDf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAiKrJPkXLJfyVFs3tTSUdBgWvxhdkFQ52wdQWcY/yJfAiEAggERvlO6+V4UOG6UQNqfA5qZLzD/0HkduxlxvVlkQ+c="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.0_1629196956300_0.3308934526174956"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.5.1-rc.9":{"name":"ipfs-grpc-server","version":"0.5.1-rc.9","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.9+c1375617","ipfs-grpc-protocol":"^0.3.1-rc.76+c1375617","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.1-rc.9+c1375617","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"c1375617b6d7137e098375134097d61edf316ffa","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.5.1-rc.9","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-tESIZDjaD0OiLlck6GPerys73lGXvTaw4c9kp5n2bbjnb+0Vqn4XLVGmAU0XmKay9I2P7/qA3LjWwR/5vlPU6g==","shasum":"83d6ee67daf0741466b573520d9147b30ee4d89c","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.5.1-rc.9.tgz","fileCount":40,"unpackedSize":42994,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhG5TaCRA9TVsSAnZWagAAJYcP/Rsv5zEcqoFXkOyctKHL\nEwbwjNZ+/t4T+f9hH/mVI3lBeAaKuEHdV6Nr4ugPQ5yP9Bh+aM+83luRgpap\n+Yv56tfjQh5nqqsdJWvd85j2iH3gR9oYawOkCp+8umqgzBk935H5EI1DvKWK\nCO9oAUA9gGt9Iz/ZKJnQvzsNZPq05EXXaTN4ECtRANueAm6iicWGofxgpOyM\nwCi5npAVqftnh4zDtGaorsRqOoovrRg4ETHKZgujChAmD0aFJIb78yxnxcHl\nkkX3DtunUnI9D0SvcKTxchNIw6sLPAIhjb3AXdWmKFZdMgO1QpW4tAQ8H85C\nKSMYnRPwu/gESo7sNlHVSZvplhmf08M1uwcllKvlcnTBqjitnT1WyFXi/Gfi\nFIP6g1GuxB3SCqfF1K+hgzNKdCmAd0Ukgabxz7KTfRO3SbTwYZfpIQLGmM/P\nigQBoEQnTN80jZwdwFhy1uUcDokq5wYx713Z86lIIOwKkU1lalfRP3WNMIrI\nAJ2t1RA2WZWgGbOySlMACPNW9teEEO+bWXvcgqdn4yRY1OZBdNMu4bfwrx+p\nz5wqRjvRA0e9/itWb0V4IQONVAXTnFJ0BfyodFJyXtjddEWj0wT1mGMYgQZh\njqpyCd5LXLpfeCQM0QEapSUFjYS6S7DGX5GJv2iAHs5c4basLuZIh1XqHyiz\nLgH3\r\n=Vl75\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCoywhtCEeHgKIFDFUIPGiF3KxgycUnEObwCFxu/mF5aQIgHlFYXtYnx6JI4V93Fb2okfMQYQ9kjM2WenEDq2RgtSM="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.5.1-rc.9_1629197530472_0.0002694071856497171"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.5.1-rc.10":{"name":"ipfs-grpc-server","version":"0.5.1-rc.10","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.10+2c1a23af","ipfs-grpc-protocol":"^0.3.1-rc.77+2c1a23af","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.1-rc.10+2c1a23af","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"2c1a23af193a23c4a710a9007c7c22b4b729c7b3","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.5.1-rc.10","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-vvlNpq5AXwJ7gBgE2X8v8LaxGhSq/7kC4RQNImCYbPavzIaAET5FdorDhQjuNsy4S9yp0TTc+LOebaydZM173g==","shasum":"ae2296a1adb845028b7cd0d808929a087e09d193","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.5.1-rc.10.tgz","fileCount":40,"unpackedSize":42997,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhG5jvCRA9TVsSAnZWagAA4tcQAIoq0Wqu3X3IPsIbg6kD\nuZR8cLkT/tv5+USuAQPnGRw+O+Z13Wu6/NfvRvdCAsmHq6DJ2w+0CTEm6twq\nDGrnW9cWaRxFq3XEnAcglcKNb9Duv1aPEHf3XgFGeBB2Ik3J1nQDhLj4SRNj\n8hJazVhpki1gAzCeV33lOjXIRfCLPcGOa50jtupY2TVMQRFBMoHhAZSr1yl5\niJ3sXNQhQIVsvsllg8sN1cVoVBSHM9iFtL7CPbbOtgaDx6Oyoo23q8b0yCon\nONl12cyS0ZYSF80IoqOv4pnfC29Zn9GSA8p1ZiT6EnbQG7spjUffk8MHfukb\njz058bkPnjXMJ2rWFWX/5PyCTXt6jHE77GAGNMk0cyMgtn9heJ9YWCh0HQ7G\nueLTPRiHhbZD0ekJG+kxNpTQxB0RuIVBeLEhHAvBd1PBim6doRG2QIg40V+n\ndJEmJtpqP600PPqKWStmqdVtZodE8TLu1A4XpfIobb+RUIGUN9P6m7LTIGGV\nsD2c5i1xqpycX6wEq1/e1RCrnjrELue1m8QRHFFAni24UH+49hbqyL+vWHyH\nWkhUkLOAwNgkHwSnKsFXfq0JRVNQrPpD1tce9/6neHNQOVs46iiESgVBaVrF\nIzDMapuBwuloQ59PZOGrxufgsS9VRCz/nU/G/4ZhjZ+Q3AdXpnqQE0gTVU7+\nwEQA\r\n=+MAY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDekXH7//7E0fY/a0DzwSIsteoBw1+Dhogx+AdHDkQO4QIhAPEGRlv9jXdGKkRhtXK6s/yo6MruqAQgp17mtkFhgl4v"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.5.1-rc.10_1629198575518_0.45929957558750045"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.1-rc.1":{"name":"ipfs-grpc-server","version":"0.6.1-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.12+438110ca","ipfs-grpc-protocol":"^0.4.1-rc.1+438110ca","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.2-rc.1+438110ca","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"438110ca4bce91dc771eafd9d6589573801b16aa","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.1-rc.1","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-PA5DQBtdbOOBs1P5CdrQ5Wz7acJR1N074a9q/iEmBR0Ptku2XFBx9saKvkGVkCCZ6CFQ2OU39S9fhmPeD8wxVg==","shasum":"39fed8fa4245eacbfd12a9892fd9cf2a7f78b1bc","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.1-rc.1.tgz","fileCount":40,"unpackedSize":43355,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhG7HlCRA9TVsSAnZWagAAOgEP/3fQVDnXp167oEsoy5fC\nOi5tm8PtNpQRy6DUREKxNfLFedoW0E3vFbTcEJGyLgH4QMRS6qwxZEYlA4u9\nFhaenUgikLfyTh7IX2PlL17dtz/7X3XVx7QiAHdezVsXK7hP8nvhDe7cwSrK\nO/kFKK7Nf+m8pvSc4UK1VnabjWoaQ/Ofuvf39pWux6tKevAtfEf7jgzBdpap\nzzaNrvI+gXblYUpSabEoGlE+Oy+ets9556uFq0h7YrsqRa2lZTBlwxHe6Jcp\nY9hedxE8IOqbfXbfWAwoYGqiTCcMujPvHR1oAHDCiBnH0T096WW41uHwBGdN\nYCgIx/wD/hW4LkBXs4xJZLWAR8PSxBN+XYcojCWXrtj9NAZh5n/HseuO6LW+\n3+w+PupGfxQVJ+HJa8uWQ9YxfIECyWxd1J9jdirhVbziPyjs+c8w/Cn80qcG\nDypbM57eVxXcPh8u8tXSzz6w8OOd2spcDMPa04HWnujxzF4Cv+r654XYN4Hw\nJn7NZ2sWxpR4wayZNZCKNzofWoPFT0LPgqoc/aTpb8O/FTp/KHkD9cqyVSgx\nMbqU5xWSlUFjWD67rtU8iM7CosVhaHxqYtBy4X1WKJ8VuEO2c3rBgT1Yf0Ie\ni2EHFPkzwYkRFeCr0xqCZLZXDpk5Gv/hAbwkE7B5jL5ZG3eCHiZtiKt+N+Hs\nwBIp\r\n=LEtT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCJ63bQgdkxgtFxnbMUb3xrQ7cveHYhSWDxC0+x7m9XegIhAO4wHJtpdThKLny9FsQs1qmBBzOzmUGRkwKvO2BSh9w9"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.1-rc.1_1629204965137_0.23139090049702915"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.4.2":{"name":"ipfs-grpc-server","version":"0.4.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.6.1","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.9.2","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"5d739b691addf328c2865e649db1c52a00d30711","_id":"ipfs-grpc-server@0.4.2","_nodeVersion":"16.6.1","_npmVersion":"lerna/3.22.1/node@v16.6.1+x64 (darwin)","dist":{"integrity":"sha512-rXb7vbimfDA7PXjI1ZKmVzwNk5nCxWZWRz5q2RX1jDvmESO987l/80TUcvpXR59Ft5e62bOCn5LxGbNEQfafqA==","shasum":"a6d95564ba59b705b5eb4995307bb5e24d1ee4cb","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.4.2.tgz","fileCount":31,"unpackedSize":38137,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhG8M9CRA9TVsSAnZWagAA7mkQAKHMC63r5qPbKpliGL3/\nCCSG41Hnhq1UL4jGTtiprm8wUUz9FRhJ8N1Tfe6TLdlFy3DKxTu3R5BVxtgX\n/jixDRiW0vfIe4/79nDVrl7wjH5GZAC8H+/nmbk4zu+ixK0anTfeGVw9Jwtl\nE6g6JTUgy4BCqqdcNJ4ln/xi4F4eIQILrgdGQLizE2mReiKzLEv+uQkcsOLG\nzZ+z5xrzxjnpm+gaXGCWlOY+z8UquKTfPZiLNVsJ+ZFx8ypcoM/MNsFGlDAg\nqIRfYzdPd05kvJn+pbxF7S0fho3M7ACm/AlsLemquoRUbn/54aq9wXgd6fAm\npz+rqYecQ0JYaRY/doMnlVm0z318jwADCZEnyaY6rgSMuXYQ0b2fdIOZcjtJ\nVl6KypdFXh6l7dGb+MfVLetE5sPZtdicHP8VPPQrdti8l/02nRTZADpKmCfB\n4FsGILsQl3Tizr7T2Bwa9/4GvS1oDv7vSwrWqp2o+JGTvPfcGLq92IPl4Fc8\n22T1me6CYvgfrwo30LGRGPO249UdGjjHH1dfbtI7zt3+EuJLl0SsCD/08ezA\n64FRrCaTCJ+8M/IIBDJN4Gqlb5zQocmSzGocHXho9kyfeG1OyIrqgQogrrZo\nCODXymdO4/3Yn8G1be9Yy/SrJ28iDgQvH9AlrR2wWDR6QqNmzTHticxYsYU0\nqPa+\r\n=XlSo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGq9pBytAk2auVU4z7eDWN+V9r8yiA+rh5pqM9kHC2iRAiEA8aLNs/Ljaf1XcFwrfMj3OOrwodOHYOqStWEQj7yteO0="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.4.2_1629209405343_0.3969164014707647"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.5.2":{"name":"ipfs-grpc-server","version":"0.5.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.0","ipfs-grpc-protocol":"^0.3.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.2","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"ab52012d0367e121ac2787fcbf1ad6c928d28479","_id":"ipfs-grpc-server@0.5.2","_nodeVersion":"16.6.1","_npmVersion":"lerna/3.22.1/node@v16.6.1+x64 (darwin)","dist":{"integrity":"sha512-J7Snm3P973SKrL1VDvq1pfjaT1jYlBAKTsL23I1x+08aj+Vqybt2PRe2JhGesQvJWU6bDV6DWFA1sJTV6HfD2A==","shasum":"05730dce901bc5664566d7e34f3f7ea8e0fc5290","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.5.2.tgz","fileCount":31,"unpackedSize":38813,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhG+9OCRA9TVsSAnZWagAAdmIP/iNc17tV6eaoLQUIb/aP\nzeMwQ6x3q5BzfWXzOoIGemHjMrZM7ZHYrqLl0oQi8mvq757qi85cSS4Y/Tls\nURO65AxA0PVr1q0v4Oh/1pZGHF/pnUJmh8RrXJsFTgpqgki0T142wuqw8Sr5\nyK+NKSWMp+d0Pw0q3pPXhWLLAieRN/t+8jVVcLhzm5uNIuQHaqUxgNsDXFUn\nwczuQH0arb0b39yKgFf4W3t2uvRJYcM9UBcjtX73Cxq2ABjueftuPQBt//Zi\nc+zEyOZLs2qwo4SYOt2zENNvxFe+IImxpav9GJyttxyodZWv9bNfY5+6Smik\nOS+Jb6r4TbtqoRu+w/F8CiOzDST6tu6L5ATNVkyNjbcUCIBSRwqZLRFGTy7U\n1bphnD4yeI6C2zZS+KMHWvhEaeW7W8lNxWgpylHOd896KfjvEN6RQlzDLyEU\nLcPD/IlNB+boXZmq2ldezJ3S080kv4ivu1TEy3voefmTQJZbHEOkxTnEhxy7\nhCBzWRZeb3JjZM0sbQR6ulgS3875ylxsTxLvMi1MghCVfX4smvr7lSpODZt9\nfXLWstG2P0q/u9QUJuT0Zhw1lRzuSOWr81OpT8zGBCXwm5KmIMjend6+T8q6\nA89rs1rIWLe7jbGXvMacSc33oNuofBPE7j2PFup38dKxqfvc4P+aenqAv3o6\nheU9\r\n=R73o\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICUBVU+DxnxR8LPyT5sUkLHTO4f/65mTem8T5FTwttQYAiEArXxHhbYmzf6xsvczN/n53byN7dbg3ABvGdoAb9kWm8Q="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.5.2_1629220685805_0.8621683329753866"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.1":{"name":"ipfs-grpc-server","version":"0.6.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.0","ipfs-grpc-protocol":"^0.4.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.3","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"20e7c54247a7f6bdde374025a9ae4a23ee8df0d6","_id":"ipfs-grpc-server@0.6.1","_nodeVersion":"16.6.1","_npmVersion":"lerna/3.22.1/node@v16.6.1+x64 (darwin)","dist":{"integrity":"sha512-i8kSneMNbuUjkDtieQBRTW5U7OPjA/cJ50rUnNod/OQEoI55+3NyIWz9VZ3rASsstbbo5IlslVCb8NNME76JMQ==","shasum":"bc6523e2dbdbdf01282222b49232f1ee5bf7ffa1","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.1.tgz","fileCount":40,"unpackedSize":43475,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhHBTsCRA9TVsSAnZWagAAdzwQAJkCayQ+46/b8AeVdN5W\nZRXboerrFbf4iA3/tsWhrheJrZFwpq1DSmupQEXFSmmT0H+crb5hURSZTC6e\neOqcp18OrkwlBDbVXRR7mGY6AIe4e2CtrfZfPNQvV3UwWgvAf7XbYip3eGXo\nBd97G0+7Gwtu2fB2Yi77WXBxJPfDw7AZK6qJmAPo6NyPVQDb0zynsAPwUKm/\nsPZAlQxpEWMiK1mudcPUHuwIYWfa6murYW5OgtWwdWE35CCprct/V5exqh77\nP3MENFBTgmI5tDBuj/XNwwzZ+GA2+GKaCXwo7H5pHS1Vr/agOKia1+UJZbsP\n+i4ja44xQqhvHZ2JePHg8WliCYPUOn3nzYGZNv+LWbmCUDim94/KcQW8UE10\nNRvcVKs7uYHcefB+wrJMmgRjNhA8yqqBi9FsMecSit2b+lqDqDa3P1LtQXoF\nhYj14jmoPHQNgNMC67bY7Ru75ZkJyLDyoaa7SC5qk3VPPVC9jmO6QwtgQm53\nFiTqeQkfEeyJIDuAWUtzFl8PonFEFHbJX88ZXzXYld2aGPqiD2eOXrUaSdsq\ntpTHFn9UhJNUb7Tit21q74ivCZfyCM2ttbtGOeJWNQeuDNOFjKOFbjqH+43M\nXP/gjRGsnqwCQo7U1TJNvy2Jx0zIJy+A6BA5QpYqPvq2JPCpPLq27ET0YK1+\n/3lI\r\n=GgMc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBC0iExW6pT5CKhNns11Ji4GTcyAPQLc9Mb2PJk7zlkAIhAPUzwA2taA/IIQUeHMTWeRX1JUzFpK/Sum73CpAxLJYx"}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.1_1629230315823_0.347339652215074"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.2-rc.1":{"name":"ipfs-grpc-server","version":"0.6.2-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.15+abcca045","ipfs-grpc-protocol":"^0.4.1-rc.4+abcca045","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.4-rc.1+abcca045","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"abcca0453a2b769464a46b23d1f45319d62d0aec","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.2-rc.1","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-tGpbeZtgtKjPWD5tjHhYsNU1VS2MO8mZnU5PDYTOeX67ORrSL/QsD+o35A05N+Wj96k8DbDCBdWb3gWM0GfG+w==","shasum":"11929286b3c39b8cd8973f2b879c58236e19e139","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.2-rc.1.tgz","fileCount":40,"unpackedSize":43532,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhHDBsCRA9TVsSAnZWagAAHRgQAIZE9QTmf43Ljwtl/dIX\nOLN/BaWkYtHJqB62bkd0omfy3LEYaZL4JKmrmBCvpvUjyI32AJzVg5I/1Ed4\njRp7hFcnE6QHXMthi11008m2e+C4Lf1taL5SZddqVcBuAxwZnXZAfJ9LeTt/\nTph7PGJvhFKHfnTs4puv/cV0NqNlceFZkRvzuqdshfKDNHoYd7NvdcpOx6/h\nDIOYV4YglCcZxeBDs2SrMVqzdkJY2DBqV5/9UjrqRLW39T8ZVSzqApxfMHXl\nYvJ4Xi2R0Knq7t8oxAI789+r6oCZxNTasScVmEgwl0wF8jH/hNFYg7rn5E6r\nVzTPTJzTWrPFxLkVLqtVV9E9TaMsJcHfX1IY6baCdSvAJsYec75KUFPuX18y\nknuUosGzePtFVtataT+QNVqYcNcFUsXDH1UFmb6Or1Uihinx/4LzyXGSX0ym\negO3A6RPqXls01GPfflMyd6tQYfsDIup07b/R4zSnds8hKJ8nn7ED6Y8GUdj\nf8N6m3qoByWjCqXaXu5w6mcaWOlJbdAuE8V70T3XyNLiJx7TfpJw6pGHvDcM\np2JNUA4cUKSNAmhczq0Saed+wJ3hVda7JkSy90GIQa+8TiPWfN3nMXWmjvNc\njLpE1fYBtg3kgvzrdxVE8OT3NwX3y6HdRF+WO2tjZiXCYSEmRz1n/peQx2Pp\n6RVK\r\n=CF1w\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID9+q/3i0gBlHhMfY+i6z/bh8bIPNg9NxQXJfOu5kkFVAiEAsxY3tcLy6QPbsvxgeXgGulZ+/nzOUlCsgwTF1PeUizU="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.2-rc.1_1629237356751_0.3442162698729152"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.2-rc.3":{"name":"ipfs-grpc-server","version":"0.6.2-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.17+beeeff01","ipfs-grpc-protocol":"^0.4.1-rc.6+beeeff01","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.4-rc.3+beeeff01","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^2.1.6"},"gitHead":"beeeff017ba49c3a171d8990389a67eb5c3103ae","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.2-rc.3","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-lgPKzfU/aFj2FN5QwXvB/cCH+YZy95aial5ijKKj9jBeFLYhnw4yUvTJmWnkv9D5CsGIBhit/Dt908wmC21byQ==","shasum":"8656a3eee76553e70e967e388294c573b9db7bc0","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.2-rc.3.tgz","fileCount":40,"unpackedSize":43533,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJfINCRA9TVsSAnZWagAAx74P+wd0Y8KOCLH7ZRBRfcd7\nZRCNFtSKimQTsY1L5B1iKc+dGeFA5ftqahGzM98N+sG0H7W8RD7MY+73KY6H\nrvI2yviWS9XvfimeUWP3Z1Vb4EiFGWFZUqPNB+xt416fWhrtdXc6oTDxYc/3\nMzjwDbJxeNp3o+Do8TSNXq+JCWlPH3IJM8GATrNrwNJ+o5Zad4334WA5iEUO\nWEiIOuWrduekLpLpOnrP6WjH46OPFjsavvPi98I41n3i6IaztcENbMsME9lc\nLpt4ktsd7QWUa17zkstuwf8ITUZr9G5aDJs0NsX597h0RWDSScEtfBOXn6Kc\nJM/BMb+SpRZv3CJQqyBkcVh8AdHXdVAYmKkMxo4hSQI1tv4lDjYBVJMTKIru\nAFdWWB9ursaTG8inWcZDsbndVeWMAsOzkRrX5EIt5hS0b6j6j+EvcBNz9Z8g\nVXOWVorx+1f+32SZ+S+B/iZDUiiN8NAQfnYi1t2049fHAdTBz4yx5FcDnDGO\n2hKITjyBBBUrqsxMWXLFWLO1sAaDQsjYYEPEvCjG6iy8+EScRGouJ4mzsnpc\nAjRMhVuOFZhA0BWGvZTUrzCCfsGsY94tNLrEH78jMbpE5egJxPpLRcG1BRO8\n4V/ZD57T1IIA/7pNlohMvqztBQwFHRwWKq9zZ7Yi4xnwrk5VW2QbvBmRWzxa\ndu1u\r\n=zVzi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBLJSDcA34nJ76tXtMNB95sMLL0ITzDb1VAMWqNe/goHAiEAiGFBKItisMnboI+4Z6hL/7JcvTVLdPYOsfFWhtRQ2sY="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.2-rc.3_1629876748930_0.9500216384251443"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.2-rc.4":{"name":"ipfs-grpc-server","version":"0.6.2-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.18+aded7dcd","ipfs-grpc-protocol":"^0.4.1-rc.7+aded7dcd","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.4-rc.4+aded7dcd","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"aded7dcd65896586bd46024bdb562c9646056b7a","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.2-rc.4","_nodeVersion":"14.17.5","_npmVersion":"lerna/3.22.1/node@v14.17.5+x64 (linux)","dist":{"integrity":"sha512-AI7D6LpE5CbV7gZt4h42HxIzKcprPOA58MiEFLY2//bcEICh5YppyTcpPeuIFjwf6a/77M06HlboBb5bwyDMxA==","shasum":"a0f03c08a90cd851295b2097a98f5f9e10cd6fb0","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.2-rc.4.tgz","fileCount":40,"unpackedSize":43533,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJgTmCRA9TVsSAnZWagAAFCoQAJmW0coyHnWfgQNI9zA+\nizTFFoZDIw2B8zmiX7nUk+DngB+KcqZvn72YcptBSQumnENAuhidr1t4RMgk\nuTJ5n+9NyOWyh+rWTNIW4JznpjR6QJvLw5A+5G3HfgwxpDylySudPZzbtZP6\nnLpRIIJhuZ8LQhzWLV6R3c9M1VAPN9LRY/bk0DnfLhWz9YvmFH+QB97o3ys0\n+DB45muNL2nyVD/TSR8ve1AsSeOx4QBmOpjwjI8O9hc2lFIX9P/gC20R4/Qc\n3sdrYHosQs4S/iJBu1N5ZsdEQiHPBlstBDMkffQgmzuXJrm01cLFJWxh3dFn\nNuNYZ6kgINk2pojvHmQSHQQ7Cww6nocjAyr1G6MMla/x9RouCokapmHAJ5Ac\n53ipUOcR9Jay58bKnoacA+h7NAkTtz9v1/4yIbIhunhBmj80YTsD5sZEp/Jv\nWy+eQ+B5+ekdNZ3MXRljH5ctXFYa1/1mNeW+7q3y35U4WmajqIW0aQCqi85r\nxuznVdAZXicgZF52FSeSx4grE+lh+eldRuXbF0DQg/aaUAXhZE+ar5+65BUy\nJTT4h0ltKT+UeQ00fLE6PN32krXJdUvYk+sMkFDD5zEYPAz/9tsz2GGhQ2qo\nWewajXKbuMuJd/M+MU1jv0L69UrU8I4GOqKwUVwIYJh2hzDXl7HkwVZADyGt\nFcF7\r\n=RG+O\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwGIuLXMYYCEJSxciJPY0OQytqE9nRA7m3TwBSoZVrXwIhALrP4XWUhO1pcUL+YSG2+7fjl5dRnLIbdnbx4PzPW1R+"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.2-rc.4_1629881574826_0.7225269476217855"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.2":{"name":"ipfs-grpc-server","version":"0.6.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.0","ipfs-grpc-protocol":"^0.4.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.4","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"6ad2b40be914098981a2dbd370396599a918d0ee","_id":"ipfs-grpc-server@0.6.2","_nodeVersion":"16.7.0","_npmVersion":"lerna/3.22.1/node@v16.7.0+x64 (darwin)","dist":{"integrity":"sha512-ynTofo+fsCIH3T5SOnbV5b4x9Qc4UGUKowaiNSx4QEi/6P8MIKMrGSeEdnPVSiMaaRPh/tIjlri97JIzac7D+w==","shasum":"3749ab60be67cfa8749ef201c6259b6fe86cebe1","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.2.tgz","fileCount":40,"unpackedSize":43957,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJmgbCRA9TVsSAnZWagAAiasQAIgs/epgAyGn1vt/90iQ\nlQgfy0giUatm8dNRxBZ4v9hAEan6kB2XOcgim8nAj1WPjHTv1rCobWdezZkk\na8kVFAIIB96fPW9XNYPBxWNRDTZBF1msOpkXzlDAEkOStohf9JYlZ2EjMnsb\nOGixIU9w09flbOa8x16Z2ZV3BRhVNi6Rxk3ha34jwk8RBb9MHtBployb/tJI\n1XGL+/PdvVCtDYoIosOAWg5aCVw4sRrhw5yj3TpU+hRzZqjS487nLAf3V2sR\nKUE3VUacbnZN/obPZvO+F/uZDRhHwdsm5dxSfuYNeGELUWqequCv9Ds+vgLJ\ngXtKeiSwJLtu0ZjyPuUWspFGgL1FZefAsdmw5+6znWryMDA7W/8S2UpEgcu6\ndW/9xVUzYeiwzshhx8IiIun1M/6mNC7Bf5A0vSJmyZVZX9cfN01IfJ7eqsfd\nfoaSXps5qkCKq4uswJMQhHkLEHylpApkXJ2aR0VBvJz4UhEwDIDx5FUOtLxA\ne73WcHitIOUOUAnm/l3Bg+Ylxa1HckHW29jK5jgjDN6yTELfgCcK111LsACc\nR84nkVjSEpt7m4DSYj8buzdlipT56EFAemfJuhQyxfXhMsEaG0a9I2MvpTEn\npUEdT9quzt7Hwf8X5fkdDHbFsDnbx43KXF5wDQkcxYmMc6TZd4dB11MeAN2W\nK1DS\r\n=LNXb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF0ExMWYahI4u7BByM0ar5NJvrzt5DwcLjOete7ZSsgWAiEAkSzIdr36ziup6bEAzLPz1jXkgK6PmuSON+iqf0NY+JE="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.2_1629906971323_0.7381315967223598"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.3-rc.2":{"name":"ipfs-grpc-server","version":"0.6.3-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.25+ebb6c552","ipfs-grpc-protocol":"^0.4.1-rc.14+ebb6c552","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.5-rc.2+ebb6c552","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"ebb6c5528eee66d07ee64c4ce105e9b1228cf857","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.3-rc.2","_nodeVersion":"16.8.0","_npmVersion":"lerna/3.22.1/node@v16.8.0+x64 (linux)","dist":{"integrity":"sha512-1EBOEaP8crK3Kz65b8YBPJdUq3PRerwkJHXJjWOfSJ1PxmmYpW/QRBx93hQaSU7DJOz0a353aNeCzQBR4sL5aw==","shasum":"dbc8f6d5f70e056608f2de5e8bb9992fce460b4f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.3-rc.2.tgz","fileCount":40,"unpackedSize":44015,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJ2NfCRA9TVsSAnZWagAAyMYP/0KX2utGcM54pQ1P//Xe\nvrll3BXWCMn7oVBiU3cr8kPpTfrMCsMoZLwIumJlxKkrUIE0oqgkyQM9vahh\n0uQTW6LxkV4/KArKlBVWQdoQdUqeBbc7qrkiPzq2ORErVIFQXHQhQaI1qnex\nG0Y6EptJLbav04/DaZZCD9N+LMYt2VcgxvKD7iA7bTqSw9xco0XUQxQyQt43\nqHYz0Gpxc2TjGqON+Q5rmWd8QWF/WB0iVntJH1OT6KBje8Xv+Vdh0mqwcUvd\n4N5ffyeBj5auOLaJec6qdlPc1Mc1/0UpYpdReixEAO45mVqciRZU08ol5MF+\neECgI1HzqGTFId+XhduVJ4QR708mdQ+266/LUNUAEapGYkO7yHgtx+QYIOmM\nUKp8No9BFGFowFRkSdm8P8+2q+d7XUI2ftsMYJ6sod2EGi5nKgztp34nwa/U\nOwRXgaour7L76FgswWq342lYZFl9aBPxVCKcHl2lVsjLSRyxsob8oJxN9NKp\nllWJXNYqDBaeNQM/iuCCujgUaNqLzWGqSNXEVuhbVoOPk/esGOysQUpPx4av\nSyAIdf/JKFR/IGdKw4qBrzJkUwv4xFkCDGT6giygz+jzG2iW0dUEsud2wKrq\nrPaD8bsxApaoLxdRmATZPw+B2XclUy3ijeJt+Bv6njn2Q/C4A5wQtEaPxeNv\no1x2\r\n=QyXG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBAmGabAR821AySQIyZ1QN+ogugr1iFvRqK7XXKQf3HhAiBkedv4EHLwC5s0DZWPnu6XoA5gIN/1HiYRtmstyR87Zg=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.3-rc.2_1629971295006_0.6625838345008865"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.3-rc.3":{"name":"ipfs-grpc-server","version":"0.6.3-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.26+6c46a3cd","ipfs-grpc-protocol":"^0.4.1-rc.15+6c46a3cd","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^34.0.2","ipfs-core":"^0.10.5-rc.3+6c46a3cd","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"6c46a3cdaf6e9f8756632e501019923a01503282","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.3-rc.3","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (linux)","dist":{"integrity":"sha512-0kq5U/0HvR80Welq+VIbKBPizdyAX3DKUm/2AYipkjTg4MCi2PoBMHSqMMYpaE3+FfkK5BmHgz56QXPfPIwtpg==","shasum":"e42a6bc7d2bb95817141077881687e3075dfcf21","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.3-rc.3.tgz","fileCount":39,"unpackedSize":37415,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJ3aQCRA9TVsSAnZWagAA3noP/RSMaUr2G1170BJ9W/jJ\noUINMlrgN0qfUsDLHAcGm72IWM5tR1IHG8AuaUwW3j5dL4Bj6NUHl3dz0Vb6\nGO2hyKt1e7wl6xPHkQ6m8lOao1HlDmuyD0NZz7XVWpPfGePgOvpiP+sJH8Yy\nT/hTFCwNErlKNbrk+Kk9gMLgfzzsh8YZaGVh5StDGcwwWx5N8psx6MYTf4gR\nOajKInj9ALcOkUanitir5rQ0NqvZpAE1c19/qEMvQAWdjpfNIxMVDuxa11Lx\nbdYvEktkkC0QzvE75TqPjxaQQBljpvuWUN8Iiq+/K1xLk7XyKNax3BoXC6+Y\nvOQMt3sV7qU5pWhoLITIrqjnRwMNtSYd6mTUgRzRsKSeZHQa8RRkT84h9qzB\n3/BRkEY8Zym1DGMsF5XQzZuCCvsuIoKb5czqyTTWhAKTt5sf5Fz4QMjG13k0\n2jpm42BfqGO4Embc012UZ3U5cJaTjtWZTvRSKNINoKBy1FcMLFJFgnapCQtS\nEVFNsYSo9NTAe7WRYyadNUjCp72eOAVIMDxde1TpwOcUwSyKY76WyFAgXxO/\ncQWffbJMUoNjrXVmyVqF6FskqxmuxIUDRrSOak38J9oyd7AgfERGCZ8QQ7RR\nBu1yxtMON8/SvGrj4ERU3cFd7x6N9Ji8lEWi+GHITy9SLYXEbzMG3kv05dzp\nqriD\r\n=fucN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFt7xlkvyOJjSF9Sy/hADqnwJ7pyMtct5Ixh2fftWVoBAiEA9l4sH7xU8X+FTLJZ/A/T1/OpgF9EvX67xTYZBlHF390="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.3-rc.3_1629976208190_0.2758910682859754"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.3-rc.4":{"name":"ipfs-grpc-server","version":"0.6.3-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.27+1ae25d01","ipfs-grpc-protocol":"^0.4.1-rc.16+1ae25d01","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.2","ipfs-core":"^0.10.5-rc.4+1ae25d01","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"1ae25d01d93d192d8242c7ee48ba338064ac9e03","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.3-rc.4","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (linux)","dist":{"integrity":"sha512-GGkH3GJBoecIPcFobZavYaiuW8lg4lEwJDgNSn1Bij3K+gQ1ji0HIlgUw4DCj+UcDOlDIu5c1pjcL7J5FHjOrg==","shasum":"8c81dc2a0bb82b194c13c64e28ab4c07257516f5","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.3-rc.4.tgz","fileCount":39,"unpackedSize":37415,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJ533CRA9TVsSAnZWagAA/sYP/AshDWakAXdL6MnHpKMr\n8ggfbtel/3JzMb4p8cglsC9TSxRF5g1WLwHjrzCoZljx2LYFaNdB9mXU8T6U\nigOIjT2svRsPiit1RKtEPWOCXzX9uLXBdodho7aHcD21qvsGpxH4hPVzzKO4\nGC3XSpiztbfUJFNBcWWDSCY6l+LCvdPJ/IxheFupHYYGfwvyXZ12z7SUXcr4\n0Lge/t8s/Tf4NE0fa6fXF3G8aFhcGXIlo6Tp8NFCvwQyjlr1mxdLTiDcqolJ\nKdJ4dveO6VpoSASwGY3C4o7TBdwYbiHklO/AM1bEDdOOBE69iuzpbjBY1s95\nMdCqjMUbGXa8Rd7KLZb8fo8petYIS6j+HKyajIpMZEIqMwelijAqyjKqAYLL\n9Qw8um+WZe96ekT6z/Yxb7kncvPEbB3q+DvPqG+AtsYOuZByG93Sw2eKclla\nsZQl/c0Of77KDC/XSZqyFOQH9vC1CSRq4YRPScELlOe55Rc6coK7w744fnVd\n7FAdNf64vCBy77BN/dGRDsEeUIYWWkIS6bcJIGWRIX2lls1Hn47UJXfFnk3V\nyYmqSLYfYXPXFmLYcqvwv6LxlTAa3qr3EP4LWb55a8O5j4jGPK4tI4FzC8Pg\nznCAZMP6jy2cHwQ+iS10rnoRkDWKCmGjlcCSe6JX9p8q1stIw8d8Nd8C3NXw\nwrEL\r\n=S7Cp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDxtYz5VK+PNPCTlrxBuM0c2AxoPgukpTwVMKTXt59VBwIgJtsKFneKDtARYvvemF/bEvLIhiGJ42gb5h28csB8BGI="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.3-rc.4_1629986295750_0.49667220519758115"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.3-rc.5":{"name":"ipfs-grpc-server","version":"0.6.3-rc.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.28+6737f38a","ipfs-grpc-protocol":"^0.4.1-rc.17+6737f38a","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.2","ipfs-core":"^0.10.5-rc.5+6737f38a","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"6737f38a27cfd7a7fc44afeedb1a7465cb17a3c9","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.3-rc.5","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (linux)","dist":{"integrity":"sha512-ASQ8ODbS2PBQv10ZeTLIcG2kTWLadgxpfgAgDp8ffNUQbEXYNKnsnCEeHtbDnJvsSYZHuAVrVKOBU+Lnfqem+Q==","shasum":"9abab5b2ef25900f8ec4c45472cfeb9c14dae728","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.3-rc.5.tgz","fileCount":39,"unpackedSize":37415,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhJ7aPCRA9TVsSAnZWagAAW7IP/R8Le0sbDiqOYQBlVrT+\niAcKuYty7NTeHRUGuhcsgb376JzPEcm1VbuhUD1bh2OcxOKdQLpQg0aeaaIy\nAVgxFsRBwKCZszCGWa9zMtR8CExcayjaS+GBK8ti7ECp/BAux/RLyqv6JJep\na4Ldkq3e2yRqpP6ykDNNMWB5cB9ZqxkcmKBcg+zv3HzS7w0w5nL5iEkAvoEg\nsQlNiy7Muw1vy3S4KAUR0Atd8CvvGvjQyYZzez9gepDYvEPXLhtuQq44YEbQ\nAwHObyHCCtUHl/l+Hgr6uoqwFb1dUfUYwyEsgUAQPGhzebUYnbQd00V2wEw0\nllFD0fj3GM0gPHwfjM32yGZlSMEgjE5dYAWmDJV9i4PwHFYpmmVz9HGNbSGL\nswzGz9HF2wq41GzKIrkOYqKlq0D6mbVIy9DigvILvY4vU9ZKAcPOKVAuu67b\n9y9k0feTE8cmuwYzPSX9ddcTVzC5mmWKhWriusLg86aiURpEuWxgvxOQqCrn\nyndnIMxS3Uyj9L5E3edorBkuW5gA91t/YjjVEswtAbmYtcOZIV98XK9sr2eG\nRedZGuaqyZTXd9ppAIorZIVP8XrChKEGt81soY3BA9wj7MzJ0LeNCsuQxwok\npNnCyRxLwiXT5YvcTl4LsaOfLi38lOoC5d8Ed1QFcJHTMtvlXXbN4xodb4es\nyiUm\r\n=9UtG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDHq2eT8ieOidEU7b+K0d8Fs3bcYrIXC9CJl6p7oflUMAIhALk+LlxNl6/A3x4Y7M7/unxCwgySFY2pv8/ZQjkK9/yP"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.3-rc.5_1629992591860_0.9353715660092201"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.3-rc.6":{"name":"ipfs-grpc-server","version":"0.6.3-rc.6","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.29+100f54f5","ipfs-grpc-protocol":"^0.4.1-rc.18+100f54f5","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.2","ipfs-core":"^0.10.5-rc.6+100f54f5","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"100f54f5b6e29ff64d9afb9c2c326707c5097cb5","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.3-rc.6","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (linux)","dist":{"integrity":"sha512-ZduqU10lhqbssAXUrSozoLH0gowixu6/1o5RZjDY6EjFmBsG3WrAbNUlMs4SOFuGPWQXbswkur4Z+asRQpu3Zg==","shasum":"0e74c8e06f38c9bae6b7c2760b733042aa6e609f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.3-rc.6.tgz","fileCount":41,"unpackedSize":40236,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhLjAECRA9TVsSAnZWagAAVEcP/A94m7KVR3qdNnXi5QU8\nWIJiTR4wa3ZndHsENnCXuggw0J/P02/1RYykgR9i8WOz5Zk2grsQRdpAxlTV\nY9YDtNUD9P5e6hm72BHye5/o5tsiCgg0d4jm6h0a5V/nSOVntYQr5L1S7W96\nx6t8KcWkpgGnPm/rZGq43B2sebM9/+EwXRYgkvRAXdd6+RT0/WAxYuMAIxJK\nZu1WUpbCa0m/kModK3EJlgDzBbQZI5kMDB+NJyva0pLAAXEYtXjpT0c+cR1c\nAacdW039t0K/1lLVrpq2f3j2D09KMbW/hM0H7erwn4B3hYpvtCG1fzyFQNFY\nJtpc5mJZIdGyo5t1YFbMis1HdLvxGMF9v//v3iKxBocX/yYpmz/nG7qDMIJ9\n3rSGkdjghuOE8EMQT4yP7UNeUj3vm5vA3iiR9DizEtO9JfzjmzZoMVA/dNzd\n+DHuKoe3OsAQLtT6PVxDJIA/9mAFz7QscJIAhqND334nv6cDoKJnvUUZfeGC\n5m9s6eWe7fAZ20DFY8X9JjTSKdpS1mYoP7RF3VXGlByFp9QBWyxmtT8FgfxJ\nG37gv4lyVxqIjbdaYipfCOMAkbSGC9vm7hy9hpW0+K2blNIWYUE/oymLS1wB\n9aM0hJwg6GCU3u7F469tbHHlJWDaBDNHLPrLEu/eLWEm+1GDVUkIs00MCN+l\nYNnb\r\n=oBjR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBmfpdlWe/74Q0yPAXJDMaPVVjlKIlB548p7HoFYlSngIhAJklxiGhJ2SIdz5ewoHX4NCDGVXVSRun1772DuF1pK4Q"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.3-rc.6_1630416900128_0.5511690084561862"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.3-rc.7":{"name":"ipfs-grpc-server","version":"0.6.3-rc.7","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.30+be900895","ipfs-grpc-protocol":"^0.4.1-rc.19+be900895","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.2","ipfs-core":"^0.10.5-rc.7+be900895","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"be90089554b3ff3d7adb02e76076e5cfa1d82572","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.3-rc.7","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (linux)","dist":{"integrity":"sha512-mcSZMT7z12VwcHDVT60SuBjv4suLMHamRVDiyQqoemb51tpcZDS7oJUDAT1I1i1jUicWmUUEij9Jnoidku3sQQ==","shasum":"6c8a6a28fe16ce9db99c2d923b09f355de18e5e0","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.3-rc.7.tgz","fileCount":41,"unpackedSize":40236,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhMObsCRA9TVsSAnZWagAATW8QAKBnw3xPqHOK9IOn3zzL\nvwAzVPwF+H9HDr5Rk/yE1aeFBIAKx9WaHxgXv70aRt/SuxtLs9O2nfS+5Ib/\nl54MDiepDpDLzHOmhRLBVynXFqfCQ56lCkZjVWWHP8zv1Hl9SiNgTPa5dd6c\nY14ch2B4bcuisNAAf6KOYyUlcppeCKOQieKircM36G9vLQXeawYLa23G3P0J\nim89yxBpVMS0bTEAuOmSffxpGo5TIU3iduhSun1wL5lzJFYGLb+fU3okyRqT\n0LFenxSCe46xpEtsBfsGMeGfq/XpGUolWpcn3wDjB95YFmGaBbU8wEv6NSIu\n2B6aQ0uGGx8s/FV9nzVvcST8m7P+OWpN7p5myqFCU0csTVxkGbFWZ4+c5HKQ\nfAKt4grvgHoP3kGJyIkmvieS/9IUFgEe1ZIo5PC9Lq5igoFrFVGa3eFt24Bs\nrl+kVw2EVyubi8+3wb9PzLj3K8O245glqySBJjxtrUmGZJj4JY1ykw7AS1sg\nH+otDRb01NpNSscFqQVnzk9fr3SKErXufzob2feBzNwDhUAEEFADgwr63wDF\niE+jYeT2hpRI6n/HfMisWahPOnSNw4ja40miVf43IBN+O1pdLneDMbQil6V+\nuP3En6xPhVmL8JKCDG1LzMAHkvsxWkfDvJSOH0p4DwOqpcuCQ2hGe/sIyjxJ\nZodd\r\n=Z8On\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHEpYht2VfrJb2t0OhXYXYmT3iugw/p/X2g2Sp98VVY7AiBf6TkEGPYBijgqk4ItJ1Vazh9eFhQu0wHbEUdi0cDOpw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.3-rc.7_1630594796816_0.16227159840977756"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.3-rc.8":{"name":"ipfs-grpc-server","version":"0.6.3-rc.8","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1-rc.31+c4f96fac","ipfs-grpc-protocol":"^0.4.1-rc.20+c4f96fac","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.2","ipfs-core":"^0.10.5-rc.8+c4f96fac","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"c4f96faca331a2e0db2d6de35a804bf2b9457c80","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.3-rc.8","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (linux)","dist":{"integrity":"sha512-AX+iD2qrzkZPSH5opZCekRJHpqQTehTavxwi9MJAbOio32OYjlRMJuD0pSMtmAzJF8QTdSffBm0J5zTPZHo3Tg==","shasum":"c10262a68279f70e04e5ab620a66287718c7c138","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.3-rc.8.tgz","fileCount":41,"unpackedSize":40236,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhMQw1CRA9TVsSAnZWagAAjtEQAI+5mGWBhZ+SazTQ7eG1\nBx2XCJ4LcMzuPkEA1Btslp/bwq0IKC5rmLtPf5t5ffeKb6/gM0H8T2DCMLWk\naE21vMZy/Yoxv/F/pNELkG+eHTk+zIusmjITFyxHUB4EsC1mQdNRcy1D4lkM\nFP5yjqCtQrcem2xoFDhOIpKz1f4fh0CnKi86egFAF8XXPRPmyGYcgfvc9Zmi\nFL4OY8ykpvYIaSR5oOQ2JqTsKDOfPYVgywlSTp5vfIVyWtEOrvO0vAQuSjAe\nYLM2+Ez7tOPfDKyEA62ZyU3YvWquSgMoqmKj+htvk66DNPoVKnBTH7ZP3TPb\nszeItWw9Uxc5ZWKBOGr34bWlGFOYOaleRzElewz/Xuk/c4xkUfbNV5/Dkqw/\no+/zB1yOnn8YBzl9tpaBcCRtbIhDyNuamit/SW8Xk+PjBBZSnoXXIHBzmqzJ\ngF3WR+5CnhFwMfS5q2N46KJljt9763JhrMS63IgTwMiboQsZkph63TSrn0zz\nAyO8uiQKyCkxiCLMpi3s8L8ky1kOcWE3PqQ8pq3hZGPP0uemBamJTfw6u2h0\nGN9ULphHujDOyUxAy/1+G4q+uFdylrJHdZRisTMNFF65I6BcqG5wF8LbyVfR\nFdt9f9MX4jKPQPmVxxNZ2eRDr5Nhpv/BElpm7Y9qnSy+naZ4OXYcr8h4EKdh\nCdEW\r\n=JEms\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCBvt7D6a/U4f4IVvIUxwsuFZaNeO3cVu6z34SqOIKBTgIgXZ54CyJnx6k3MftztUm8kzOstT1wAvI0ItgnIAoWC7A="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.3-rc.8_1630604340903_0.6209241779436869"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.3":{"name":"ipfs-grpc-server","version":"0.6.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1","ipfs-grpc-protocol":"^0.4.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.5","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"9d92e8079694dfbc7be262021cb9d41e6c5e2c07","_id":"ipfs-grpc-server@0.6.3","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (darwin)","dist":{"integrity":"sha512-CSQZFxWWgaNXOIatDYl0zU0A9Xa5a/j9oLVLRXGmTir+T0zAAUgRcNotrAY30e9sWaPryqO0ND8BHdM54c7Eeg==","shasum":"989205ce748358bc8464cf5f05217d4e2e963c73","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.3.tgz","fileCount":41,"unpackedSize":40178,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhMRWRCRA9TVsSAnZWagAAPM4P/3nYjOBRkVszykmb5ZIw\nLeAYPOiFnVB2HO6xWDpW2EbGTwqC4JSiAvkNE0rGx1dDcB6UC2egf2dbw3tf\nxVlipXibRNNqmdn1MlWVWAM+qomeVhuTVNJJ8gIv4lhcGToKcJj8mpLEnlKr\n1lQ+SBucDIki++CakUNrVyJaYJO+KAd9V2ZJzAETdeikJdDT0ycvUL2uVnfx\ngeJrvIuOlkcFEzkeyqndNCXzNGSnWO5QI9CLIYKVpeZthiqPyANixd/0dhiT\nT2Ex51si2eU+0eSp/VGwqKZNJY8XhUk/FSmz2np7y8cLqD0zRKQElnCIRvo2\n81mC2ETv41zBRiMVSsb7CjyRZmOWReKoEkNSMqnmVcAzVrpUA126kOIPTA3N\nDgJftEawHPB1LRgM0Ma1zw9LdiWpaBLCMT5gAjeZaE8PwFmRYWO05T3wRiqV\nEI+ZVtv6RFiAD43zkzm72hgS9ccnh6Pbgk6WpR86NdCyDKZsi9fOmUjhXIrm\ncMd1RrblVUokTfUDKy3ldbb4r6ARkcvsfrcJN/UjjqG+OhQ2ujF4ff3RptOa\nNPgaBvNA+H15wvsrAoTRF/WzPAyK/EwGayZNLtfxmDLu5F3JzZJQD/NY6ccN\n8Mrbql7TX5bKaZew9Ro/0H87IBWbsv4JhAIYiR8jE1DnCMFwTWXem30F4Ubu\nFGFc\r\n=2xqQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHsXmoDcRiiRroIycfbX77//kAw7n9mpQSi2HuGxg5u9AiBsDuPCjx2pYMfwFEYAncEBDDj5V5IppGgpdI9Ej4MRZg=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.3_1630606737461_0.735645485453085"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.4-rc.1":{"name":"ipfs-grpc-server","version":"0.6.4-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.2-rc.1+5cd78e56","ipfs-grpc-protocol":"^0.4.1-rc.24+5cd78e56","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.6-rc.1+5cd78e56","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"5cd78e56b8344b3f71fc7c578c4a50d92c25f0e8","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.4-rc.1","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (linux)","dist":{"integrity":"sha512-yOanzs1XIloXN8aYMtGVPEhi+AfYyK3zvAo2vGRbl02DW8yrU/o24wOcXsk3bMex1WyZ7BGKodygg86wPijKwQ==","shasum":"d08c62412a02b5c11246b70b1ece562877c90da5","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.4-rc.1.tgz","fileCount":41,"unpackedSize":40235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhNfkmCRA9TVsSAnZWagAAWuQP+gK0/kGdtxw9o/4hlScI\nYDNABpIu4CuLHQ/X1Bt13kl1or4syPEs88TWCNCJR9Q68vv7ZZLQcbjnF4gW\nJxqZMEFCRs0LqzpMKYiBPpbCF66xwLA+Ty8GZEw3ROYniYvNbmLdcWuKJ+45\ndpPxSiUv174yL9VcvJePOOmbj5XN2xcobObWEBEqWOs437+TLP6xXnMo2uko\nVJnDdOaAWZcbx0CzZVMqTlU6FEHXwdKqWx46KBK19vMS/6Y8gJINtylRFLH9\nKVCNJpk5+aUCV+i3oUnpYybjZ+QOaQ2rzk02c97WkEZoo282emkycZeYoMAb\nfbY8rtVnYEP+ISgtjGvuyqcVrOWh9PldV6PnF16UJWSw/lDoMNXszEMsV1M/\nT5V+HLqXhDvM2d4vtHM0V/+qY5/YytsXVeakokR0NQAdqnoXNdQd4E52AvMw\nV0HcJMkH4zSlGaGwNuLFfT2ZmiTcSjXK+4F/4HVuPWEbIpkUngFR63oZEA59\n31fsKYU1+BvgnB1AV6Z+KaPibIo6MX6WrHCRd2JNHo3pYTRSoIoOU4F77tvY\nVV4p/MNaqf2CWjMNpckoXah03rsLU4Egubz/iqLhTvP0dncz6nxg/QbSojsq\nwNFYESUd0FdrkG+X/4LvH+SU+riSQOx9zImbVZoBYaYjFr+pLniLcsVcq21k\nrqAn\r\n=SSzy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC6xqnecwxgoF6q7EnRdT6yLp0iUxCLJZU7B8skieMcQwIhAK4UQ9RxdziBO0hjbso08f3UnJzPLmggsMa7hK3VIa1n"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.4-rc.1_1630927142747_0.9628926297471418"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.4-rc.2":{"name":"ipfs-grpc-server","version":"0.6.4-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.2-rc.2+2be33543","ipfs-grpc-protocol":"^0.4.1-rc.25+2be33543","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.6-rc.2+2be33543","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"2be33543a07c14a604fd484a481032dd75fd8235","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.4-rc.2","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (linux)","dist":{"integrity":"sha512-r6OLb2tafeJnyPeBx9G5Mhptb0Nzb8Q2Yy/9vrv8hmttxyppQjI6jpvg3tVO4gLuQow0u9fjvfO1vVVE7gLKTQ==","shasum":"4f0b470c29716a3a2610ba355e0b9ed9a52ab8ce","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.4-rc.2.tgz","fileCount":41,"unpackedSize":40235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhNi1xCRA9TVsSAnZWagAAABcP/R1qJ9FOLWLwf70Zq7aB\nLCKbiNsaLYLmL1+GqimpPo3pKslsgboIlFjlrgsKqr3Db5bgZkhGef3gSH5r\nYP0wCyDH7HN1RBicHs1BjFLxZf8eWgo9jSN8hyAmfihVwrgEYzxPsrGKq3pr\ncKl63bbBBU57lXTrHqDHNMT4R7XWvCAjEYICq82dbMUkWNz4jPSZX1K0kNc/\nDd+IS8kOj+YBfwawb6B/QszHJcBD7p3iq3Vh2Y0OyhkqT7xsA4JU5Ifwci/P\n0I7dgkCBjDYy5yip4XgBXle4MfbzDBM2MCxBZl/koBa3NHC/5KrFtI2vrcZJ\nWln9LHjSmGqVuEopBagzmiRjHhbSjHiOPe/QWg3meumONDzEj0epVB1qxQZ8\nrKihMw5rijh9gMh2i02SsYdkLjrMmmnjZuwoMv5PpsplL3qchq67c7H/fd60\nXRpYwiIDg5ZoIcKt1ubHhr2NogBpOTZrLAXWbAqU3Xps/B7in7JcpvR32uQp\nXUZ+m5LdXQF5Ib/ONKepw3Pf7OufF5G9HX3iTFZe3W0mjJkT7/sDYtnGPhNi\nPxeMbh7MTTd5IYNDQWfqpd6mObgdoUhWBokntg+/gFz+Hkdj3sl4D4MCmQZa\nhP69x8/N3vDcIbWi5VUWFh5I4CH6R0ESNyGmwN2xf8Q9PYM6VhI2VwNgTrLY\n784Q\r\n=aXvI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDzR3UPthjr+OT8K8m7wLOpjLZhcN/rqXWKcrVVPYmAZgIgC+xMhOIwda8SPK3Ef08TG1SpQDcYWyeNV6nImCrJu2w="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.4-rc.2_1630940529265_0.06602617730150628"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.4-rc.4":{"name":"ipfs-grpc-server","version":"0.6.4-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.2-rc.4+84c772ce","ipfs-grpc-protocol":"^0.4.1-rc.27+84c772ce","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.6-rc.4+84c772ce","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"84c772cecffaf4deaf967c0c4e9d49c3dda73237","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.4-rc.4","_nodeVersion":"16.9.0","_npmVersion":"lerna/4.0.0/node@v16.9.0+x64 (linux)","dist":{"integrity":"sha512-DMVrNPqlD6+IocKmgaPhIqdPliy5VzWAF//qUnoyaqETKlcI8mq+L6v9h33A7r42lF63VLH8qcWYtIpZqnV21A==","shasum":"87dd689dba3ba54fafbe01e6b7cd9d66027d68f7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.4-rc.4.tgz","fileCount":41,"unpackedSize":40235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhN5tyCRA9TVsSAnZWagAA4TYP/i6qSTDeJcbxRCPhcMHx\nqheL1vD6MCOWhvY5LK9cgFJ4zzIK92lBY4WyI+IqAXZac7/SSUCscnLjphsj\nyL7kr+PF0TDl5Mb9lYsiG5rID9Fc60iHIoGfL2e7Gj2fBvPfrbB6iVO5/b+Q\n4mwn8iwmcV46xs2Y3TCVE9sWd1j93DAifizZeOe1LPuAynUNNgfSXQQET/TP\nvY67ilfrerh2e1GkEBd5iY8g7pnBKqAAUvNgjA7zP2xw0aMjoEx3UWVU2VON\np2c2DQPTWbKDpQ11KRNNnoyJjDvCcsAGaFX8DS8K9c4Q3hqtwAH6sTKfax2W\nq+jOBioHc7Prd788Ci3ldIGknnVMhJhiOWAmMYMh86yLSnyRPlc2CGlAyZky\n6Vh1f+34HDbbK4WsFCbJhHhiUlrC0T+Gq2z1OHmtdl16FxTBHanNQnRKaXvM\nKy7JV2PTAkQYEkbT6sGpKB95ynVtMN1dejHtN9OI47yLpgzG7PhCqQmeurzr\nxFM6cFVvprTDxwJSJ9JVEc28pAwA6m/kXL9VDHlX9vZGUNcAvs79iXbURW3n\njaCjkkkYeGMXFv7ze3UmX/SCskLvLVdWFy+dtyXCHdlB5Oc/1Rl5Tvuul8qO\nOjcSg4/77XtDBehuTl+4gD+QWxCvsRUeV6gGLa2nNK9YR79ZQhBHYAR5/b41\nb4MM\r\n=AVcW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqPA2TgYo2CQtab27JbGulMs1nY14IRbrP2yATQeLvTgIgLYeHf4GEkuKikujrAsMMVcN1oSYmZ1is8uWPpxuICac="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.4-rc.4_1631034226212_0.19523842671964564"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.4-rc.5":{"name":"ipfs-grpc-server","version":"0.6.4-rc.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.2-rc.5+b072ef16","ipfs-grpc-protocol":"^0.4.1-rc.28+b072ef16","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.6-rc.5+b072ef16","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"b072ef1635759a3d64e02afd7a6d853a94cc06a5","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.4-rc.5","_nodeVersion":"16.9.0","_npmVersion":"lerna/4.0.0/node@v16.9.0+x64 (linux)","dist":{"integrity":"sha512-YgZaUYpVyRCU6gC5eC9dnVBru6IhAr6JIG2QMt7cyZZmGTjEE1Hg83JyzkyRrcPYIec2WGvuLtHa3P/muyFfaA==","shasum":"0c22281a3235af4444ecf8d6c83f859a3c2ae5cc","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.4-rc.5.tgz","fileCount":41,"unpackedSize":40235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhOINkCRA9TVsSAnZWagAANkgP/RZ9pyM8EE1LXRdfmWc6\n4n2hdZj5UGWytEyZ/xFcCRAohjRcVaVtDjlkc9TJy6XES0mxwQfFcNVRw4ux\nMLV0aDX0PY7A/M4pxj+AGYp1E/u29vZKwm0gVDU6SchAfkPfKminFCFnIuqq\nqOREJYhf6pczuQKYbVL+mXHrfZJ63RCjMTdal/9J6ruPYTinVsHV9/rJnp2E\nbZj5ppYuSIIevM3RLXZGYb0A07YtAYMfDdeyyKi9OHb9bdWDaSCxnUsnkBMh\n21Kf5/39YX9OfOvTwH5J1LLNFOhi/bkpKluIfWIVwMP5o+EAU4L05iWx550T\ntuXya/msvQ8ZI9ZUKjP54QKHXxEZ/tN5stou29CUmU7EnWp12lOdXMNujGLx\n3S/nCUKpubG39+x/YEjRiP/YDH3WQu3LLCFmrazzHaQ2jMk68cjY4jrG2yzV\nvg1K4sX6DSImla3uDc03qkqOcUxNpd3qdRrokgkIQ5LXiDxPN0vvrYVbL9UC\noZdiPm5TCi0G4/7veS+eLDl35f9b4cnTh/89cRfDWr48/xLw/XKT69Vhhr49\nqu98JlES4uH1YAtEBKsbUHbYFIm+7LTbRzDH/6n6Fmwm6CaRctgSgW73oiZx\naJSZArCgVx9niSQbvLBRD8Z4pDzGdbYvhDvxSsWMX2YO6y50/UMmGZR59pq4\nPT+A\r\n=FRL1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDgOZYGtXcSK+cFt8b6+GkceRqL7h55qjFxpDSTZQDuYAiEAz4JErOzkWGbHHcw6AnGfyOYUbpJkZ+e49J63salw+Fw="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.4-rc.5_1631093604268_0.9921890675366785"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.4":{"name":"ipfs-grpc-server","version":"0.6.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.1","ipfs-grpc-protocol":"^0.4.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.6","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"7555dc28a904958b375c4037258759061745b3b6","_id":"ipfs-grpc-server@0.6.4","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (darwin)","dist":{"integrity":"sha512-GQrU1M9eUv1LJM6DpU6khy6Ihy9nTbYF2rxbYBd4cguNxRAVVAgUmP3A3VqoGe/X5oLkRy8bjM0OfK9LhnLRdQ==","shasum":"6a6cec57d5a345426494808542df8adeb023c614","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.4.tgz","fileCount":41,"unpackedSize":40178,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhOIohCRA9TVsSAnZWagAAZd8P+gIkTdMFQxr3k/2oMPFA\nMEWhYrahbd/8pq8RPbFSktBsJCnFUjps6TErw20lbBxyDwZ9VKKQwrODO4Rj\nbh5knua+0PWxkzrbDcWFQop1GAMyjVoNOhWAR2xLHfQtGZRiUeX+TleOkTmZ\nG8F7BaTrFwbmKrBXEiMunbRBh2+jYMrLsBTpsNJtVthmTKFp4lKrbo69GEZ/\nqjCOSnAnrPsvsxDekBa/Gbwu33ss9O+a/exvJDfiemox88w426fSKad/Dt3G\nlVHMRzKBVxingOu+gvb+lnZGoSZBxPDs1uHkcCEJUXHclv4MPYJTSFImNXQC\nekP2ZD7JBwRzeStH6Jo7U/80llSIuAvIHDOJ0/I6keGFltRgDyqtZ7QHf5TM\nVd4xh3eDQHsOGpxiJhmjgXlBKp/kbwgTZMPnNgyPbdRRFeN7sR7fRFJ4U2lZ\nUpBJ4QkdqZir1J3CLHpr35Fx+5z+7TPwKaE6ZJDMpj8FtuGiMXbOQ/RUe0m5\nRbMRH89rGCn9pIyVUjXUb9tAJmUy5Lf1fZ6cdbXo3mll36bdO5txrunYeaQd\nPb/QvsI5zNePlqJetzrA24HmNomheyS/Bmv9akdXfzwxiCxBVDbauh++StcI\n5LlgwMpzMVqb7JDlVIVjyByRtAlzG0jVCdoJw9ncBQ4U4coz2bxYjaRO+lsq\ng9X6\r\n=aPtw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDydobEbeLMYAHrJeu3mLjKG34CkaYnIeWMuScXsae4GAIhAMBhLa8fxFIje6sAxOcw1CapW8RFfWhg4t4FgP90+aUm"}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.4_1631095329194_0.7425799099627528"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.5-rc.1":{"name":"ipfs-grpc-server","version":"0.6.5-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","coverage":"nyc --reporter=text --reporter=lcov npm run test:node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.2-rc.8+3a8f1fb7","ipfs-grpc-protocol":"^0.4.1-rc.31+3a8f1fb7","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.7-rc.1+3a8f1fb7","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"3a8f1fb75cd49c882d013ebc1ff600a9815f997c","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.5-rc.1","_nodeVersion":"16.9.1","_npmVersion":"lerna/4.0.0/node@v16.9.1+x64 (linux)","dist":{"integrity":"sha512-fL8ehP+KnvfW9SuiG/NyCmX2T+mCHL3/1jaVKETIn5bnj7zyeKGbQFZbEiZbaPaF519f6Nla1Mxn/v5+gTX3UA==","shasum":"c7972051bd35ce2eef7ef431677f8bae8bbcadf5","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.5-rc.1.tgz","fileCount":41,"unpackedSize":40235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhQKY9CRA9TVsSAnZWagAAupwP/0/MfPaOtVXT956Uw8q2\nYdImdMwrgv8LOusFLUAFp6fLeuUxOV1WSmWneDmVseyGkhLSyrmNW0PwF/vt\nKpK7+MUsW3vtYrq0eCHYdsrNLnIU79j0j4eUqJQR57l3ORnlZy7kwN6sQtT+\n/CHgYD414q1hqzf+K10LBthf4fl1Bft7zrd0xTkrcAC6IpBgqk63BuQ4Txh3\n1lGpcHQ9+eqpJnR2k4JfbSmoH5SR4tTF00nQN3IMEh1xvd9QJO335mqNmSLy\n2OkdHGyJhv//DDs8Ma8D0xgE05y5zxXFMP4Q8Nat9xroH4gh7DWej91c2v4y\nSLdZBd6jW8wQYL7iOk1ZrbmCfsVmf7/BfbLNgAZWi33hDclY3wFcEfOvB0cT\n+koNmIRAhxwmATcUVPZlXq04YCh5XTkv5nGcTujrbNyb53dEGiF+104wp56b\nWgvPmULyL6RWvOLdAcyTwgejYuwPD3wXC7f+nPL8TIdqjOi5nrFpopJm4hDY\ncCCgxDirXHopR7h/yRLOFUUrKPkILtJN78hqyjNbdnUt4he78wcN210OcSjC\nXI72TlzBR6Yjo1fbE5sy7x9Q+1joLkkRmQVfyzSnBaWrmVwlDFA03GpesWht\nsPexynTzvw39upJ2G7taqhMK+kOadeFwhPBrW5pTEzh73YheoWxmcqn6PPb/\nlJRS\r\n=+0oD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnadGtE+fy/Ge9tpdE19zIsX7m/264idwbP9q2usTZywIhAKoJ4G+AHCbX3ylyb5ihV0kdIR93tFrFbyEVhHtX6QdR"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.5-rc.1_1631626813665_0.5443997060567454"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.5-rc.4":{"name":"ipfs-grpc-server","version":"0.6.5-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.2-rc.11+d4b4fd24","ipfs-grpc-protocol":"^0.4.1-rc.34+d4b4fd24","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.7-rc.4+d4b4fd24","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"d4b4fd24ccb37ba7bf7d587308929bc4843398ba","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.5-rc.4","_nodeVersion":"16.9.1","_npmVersion":"lerna/4.0.0/node@v16.9.1+x64 (linux)","dist":{"integrity":"sha512-qzSR27WUw0yQlutmxZXyvnMhfIdPvRHNrz5lIprN7yEDcxn0MlDdjH7X7xe/QCIMbi4azy3fZJoERvsAg9yjgw==","shasum":"ffc474bddac28a5a0214a88e1391817fdad28078","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.5-rc.4.tgz","fileCount":41,"unpackedSize":40202,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBKuk4SZ4mIXFpQ+/zru6GyhSnCTBpwcWAndo9F1HaV1AiEA6wiD7fXpBYDYEelMqVCzPBC44mzx7ldltjRHrG/csdY="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.5-rc.4_1631883050578_0.7339863854613613"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.5":{"name":"ipfs-grpc-server","version":"0.6.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.2","ipfs-grpc-protocol":"^0.4.1","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.7","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"88c9921362ea5d71f7a3af67d30765c175783b5a","_id":"ipfs-grpc-server@0.6.5","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (darwin)","dist":{"integrity":"sha512-IxIa2Z3IU8ak2nnJpCrAg3zlFeRyqitCLdXDRcn6DWN6ralTuWnuC3sm5vf6/TwynIiIIPmzLePhJ4hh754Yog==","shasum":"a5f212bf81b27c84cb344e7c46574c6128fbc70b","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.5.tgz","fileCount":41,"unpackedSize":40144,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCrP0rrYih8Jl6xi8ljvYsGtxrQbGrttasPjdqAtU9EEAIgLJ6edWgKDsVci4ujaFtnpQ1shRmlnrzVyZYxAxycnqw="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.5_1631885045979_0.9230571090243542"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.6-rc.0":{"name":"ipfs-grpc-server","version":"0.6.6-rc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.3-rc.0+88c99213","ipfs-grpc-protocol":"^0.4.2-rc.0+88c99213","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.8-rc.0+88c99213","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"88c9921362ea5d71f7a3af67d30765c175783b5a","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.6-rc.0","_nodeVersion":"16.9.1","_npmVersion":"lerna/4.0.0/node@v16.9.1+x64 (linux)","dist":{"integrity":"sha512-Uhx/ng+7ek/UQ2V1qNTtQgnqWN94V5JPhZ1S6hFF2/zCWCToWN8RKHFGg6rjCUO9KInqpDUgXQDtb+G9fSQa7A==","shasum":"2ec3aaef4dc369b4fa1a18dbb8fc0a8d062a33ac","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.6-rc.0.tgz","fileCount":41,"unpackedSize":40200,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAGW3TRGAWg7jNUbtSoPvIXrTFy7N5RTMGpeu+LLQrv+AiEArLcqDhy+aSS7LBS4Hw/LlLWx/GUZhXm9KkqXiH1zfUs="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.6-rc.0_1631885413395_0.26162213232290954"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.7-rc.0":{"name":"ipfs-grpc-server","version":"0.6.7-rc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.4-rc.0+a49a89dc","ipfs-grpc-protocol":"^0.4.2-rc.1+a49a89dc","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.9-rc.0+a49a89dc","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"a49a89dca7d9b81d390af0833bcee2133959d1de","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.7-rc.0","_nodeVersion":"16.9.1","_npmVersion":"lerna/4.0.0/node@v16.9.1+x64 (linux)","dist":{"integrity":"sha512-JIJPGy4mBU3SS8iFny/navxpiY2rI3/mXJZ6kBbF7p/51jDd6GN5iuZbQQ6TjkuHxg16lkEXYAyw5NxKcVLPiw==","shasum":"a391c8225167cc973197c5560f71b2a930c972e8","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.7-rc.0.tgz","fileCount":41,"unpackedSize":40200,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCIZLTmXdx/9rqL+bJtrkDIP72UTjcqC3fBnwo3P6DTVgIgU5QmoMI3nQGciMYhdx9oHCFk001z2+4B0+CPQy9j/zY="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.7-rc.0_1631895931453_0.3558865210894975"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.6":{"name":"ipfs-grpc-server","version":"0.6.6","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.3","ipfs-grpc-protocol":"^0.4.1","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.8","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"b5488cb3ef5ab7ea24b8b2275ffa8cfa4b7b7ed1","_id":"ipfs-grpc-server@0.6.6","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (darwin)","dist":{"integrity":"sha512-dQ7Z4p6AKfHxSBJje8sgNtaU5DuRBiFVnWOLNdhWu/5K9POkJjsUYo2CbCpur3RrCR1m+sPPf5qNLny71kl/+A==","shasum":"c168564918b575c95636c946590c5501907e7163","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.6.tgz","fileCount":41,"unpackedSize":40144,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHuAAJwziSci95RVipYgfrZ+IHQ1YV+lnu5VUaS/lXayAiBhvx0rikr65lRd+Ixv2TsY0YE3WPp59GgNf+J7ojdN+A=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.6_1631896564356_0.09198488685288009"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.7-rc.1":{"name":"ipfs-grpc-server","version":"0.6.7-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"src/index.js","types":"dist/src/index.d.ts","browser":{},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.4-rc.1+4126a5a3","ipfs-grpc-protocol":"^0.4.2-rc.3+4126a5a3","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.0.3","ipfs-core":"^0.10.9-rc.1+4126a5a3","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"4126a5a38bd7b42e96171b67e9cbcbf4efb94476","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nmodule.exports = function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.7-rc.1","_nodeVersion":"16.9.1","_npmVersion":"lerna/4.0.0/node@v16.9.1+x64 (linux)","dist":{"integrity":"sha512-1K8RT/LcBj/6jNpYqFgKaCIOA+GabUOxGEF6JSNjNrfGZHmSyI4NZHtk+bkP1F6UzaDzCSUaxtHxSPG9LIv9gA==","shasum":"102de4a028f80e9194ba0f266fc249f35d910ecc","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.7-rc.1.tgz","fileCount":41,"unpackedSize":40200,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFxsnLMqUter6ASFU6TI0rEeSEU35GOcx+TMSiRJoAyaAiEAymeL1LtGsHBppxGFM+N14OqJ2loLvmxdhBcmRea69YQ="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.7-rc.1_1632240645718_0.7791277205124478"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.7-rc.12":{"name":"ipfs-grpc-server","version":"0.6.7-rc.12","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.4-rc.12+98e3c7213","ipfs-grpc-protocol":"^0.4.2-rc.14+98e3c7213","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.10.9-rc.12+98e3c7213","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"98e3c72136abd56bb6e3a8ee1421f7dcc8c8533c","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.7-rc.12","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (darwin)","dist":{"integrity":"sha512-2L4gyE1aUv96HJVab/FQ+iBQZX3IC/ehAXPBZaTnLhVm5Se/aKNhi2i4av/Q0tCm4ht9z5/HclmamwKtCHPfZw==","shasum":"bd833318865b8fafb0b65f283807428849f26d9b","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.7-rc.12.tgz","fileCount":54,"unpackedSize":52901,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFJKuKSd5esVbMQVOfv6TZQHFeGOapixNEsONyN6Bh4vAiEAg8XLoR6GN5Wq4qfosZCUz3fI7x+8YiDkdoIN++w7Gro="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.7-rc.12_1632377769249_0.3225676166363296"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.7-rc.13":{"name":"ipfs-grpc-server","version":"0.6.7-rc.13","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.4-rc.13+1d568430","ipfs-grpc-protocol":"^0.4.2-rc.15+1d568430","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.10.9-rc.13+1d568430","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"1d568430137af97b76555b015a18718c83f417f8","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.7-rc.13","_nodeVersion":"16.9.1","_npmVersion":"lerna/4.0.0/node@v16.9.1+x64 (linux)","dist":{"integrity":"sha512-xmFoCvi0QCugryBmg7DnJcUgY9b+MqBwbYkAWbCWt1hNXeRAsWvnfy4/6SSFXsRERiXTHqXvzxrzZfaHaJcfog==","shasum":"d6f00a339768f922ff1c30489bb8339c9ae6c5b2","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.7-rc.13.tgz","fileCount":54,"unpackedSize":52897,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAm+EkhUEHmoUsu/MywrOnb3N/IHX+gAafn+fT62O73xAiBI961qFxlhGDntKqWgMt//MzJXuB+KHaYuZ8R1wZybPg=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.7-rc.13_1632378393436_0.17034815566499417"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.7-rc.14":{"name":"ipfs-grpc-server","version":"0.6.7-rc.14","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.4-rc.14+498d9b0f","ipfs-grpc-protocol":"^0.4.2-rc.16+498d9b0f","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.10.9-rc.14+498d9b0f","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"498d9b0f3c5325af2d2f93ce1538c65f7c1eb2dd","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.7-rc.14","_nodeVersion":"16.9.1","_npmVersion":"lerna/4.0.0/node@v16.9.1+x64 (linux)","dist":{"integrity":"sha512-G/vX+Cw+HJvLhxIAqjHdNpQmIJYpDbQYwzx4Fx5Mr4w25rNDZMqkPCpFZ5NMBERvW48/QOUsc60PdErpAdbtQw==","shasum":"0d32329f00f5006b3cd051a4e0458523d98f1436","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.7-rc.14.tgz","fileCount":54,"unpackedSize":52897,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCJkdLC6MuZUaeuYZV/EdrTmkoWO6i/evXdimBV/1sP4QIgJ66Pm7QE+BWVSEH8AbIhpYYLKq2IYlsFzyolU8LMfVU="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.7-rc.14_1632394073702_0.320789330844127"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.7-rc.15":{"name":"ipfs-grpc-server","version":"0.6.7-rc.15","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.4-rc.15+5de1b13b","ipfs-grpc-protocol":"^0.4.2-rc.17+5de1b13b","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.10.9-rc.15+5de1b13b","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"5de1b13bb685405ae081a824dd76e34228724451","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.7-rc.15","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-ehAf16QOlY3WOOfTm3BIaRDQk1Xfh9c4joFJ9BNiNI0PSXsy08vthlJuXUfeErWbZyjJUZHrE9c18GIBtVt1qA==","shasum":"4c5348f0d668a8015a95e5046c32d59900a183d7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.7-rc.15.tgz","fileCount":54,"unpackedSize":52897,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC0slr9R9EInsauwRyXKQDOxxrJ9O6M2eo+wEgd80mQ+QIgBXbh5sHirx91q7vpU40WWK20FcNHaiAA+FqHUD5sC+k="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.7-rc.15_1632401810341_0.18656727138881157"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.7-rc.16":{"name":"ipfs-grpc-server","version":"0.6.7-rc.16","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.4-rc.16+be4a5428","ipfs-grpc-protocol":"^0.4.2-rc.18+be4a5428","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.10.9-rc.16+be4a5428","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"be4a5428ebc4b05a2edd9a91bf9df6416c1a8c2b","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.7-rc.16","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-OfuG2o4EhM6rNJFtBXziJ/FvFAMJy7CCu9k2B0b+4cv+eJo69PCGGGd0oHRaAo1tnuInsQWNEaJs5BLe9rucuA==","shasum":"7fbacae6f3dd547972f60ee4f5153add1c391988","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.7-rc.16.tgz","fileCount":54,"unpackedSize":52897,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE4S1+FMGrdG0I8+fArRSpx+Rx16r8OHRVQQTjVR1u4eAiB1n+TonrjH45DdlAicO8AZOrnHYOlDyMp5SPd/+G8ljw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.7-rc.16_1632421991980_0.8331630310482934"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.7-rc.17":{"name":"ipfs-grpc-server","version":"0.6.7-rc.17","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.4-rc.17+b0f367d6","ipfs-grpc-protocol":"^0.4.2-rc.19+b0f367d6","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.10.9-rc.17+b0f367d6","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"b0f367d666aceb4ea8bdd532a9d8c3501f8cc78d","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.7-rc.17","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-ZJfRuGuZ57uqo6hx1pnQ6h5XKRI4aZpqGV776nLDbHo/NKzFs6aI0PLxBgrMVQw18ENsUtDiL1VAfnBvtXdX7Q==","shasum":"97a8d2d8d520e5252ab39363ceb6b1a267880fbe","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.7-rc.17.tgz","fileCount":54,"unpackedSize":52897,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCMoqtaa9ArALHy7AED5Ux2vGog0qY7MPzxzalbC0R1AQIhAJZB9IwAmNHvfeJF6ObPsbvjFmbqwPILYu5VmkPernxl"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.7-rc.17_1632482445341_0.8201135258168801"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.6.7-rc.18":{"name":"ipfs-grpc-server","version":"0.6.7-rc.18","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.7.4-rc.18+938a7d72","ipfs-grpc-protocol":"^0.4.2-rc.20+938a7d72","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.10.9-rc.18+938a7d72","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"938a7d72896bf5e5afb2ce6d472aec4fa4929a3d","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.6.7-rc.18","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-eQoXFi8c6mOUR/v5/E6J/6mourePQMaZbnn/FXRlsY24ih2SpVmYyYKzcBEw2qPva2x56aeECSkjrV2aPtccxQ==","shasum":"766212cf13a7b1aa56d8f11aa03ec128fba1521e","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.6.7-rc.18.tgz","fileCount":54,"unpackedSize":52897,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA7tgas53dQ+tgqT2xB7W15FLTc9+FYl8flq3r32ygXQAiEAjf7+gbp560PhZDPyEvHLDvIBfS0QVcNgr5ZzHRVgQBk="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.6.7-rc.18_1632487533671_0.2754035231288301"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.0":{"name":"ipfs-grpc-server","version":"0.7.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.0","ipfs-grpc-protocol":"^0.5.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.11.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"cbd3e948deb5a6489cd69d1705a0261860c2ea22","browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.7.0","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (darwin)","dist":{"integrity":"sha512-uXNS7DLCtFzs7X4T2k5Ui8YQLXtjVJOMNdCtdiqOBRvG0+9v9RaQiW0sfg50xcWw/MM+NkXPz7gJ+cJ+miqKuQ==","shasum":"75499c7250f13505eb01e36e212b0207f0991bb6","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.0.tgz","fileCount":54,"unpackedSize":52837,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDx4+fV1nFfSPb0g1f7eFZB6TbkTDPVtnLtfq2Irk4KNAIgN80smPNyZaL/gCqt9EJyX2VojVzPlCvivDu7N94gkbg="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.0_1632487753544_0.053315211687009256"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.1-rc.0":{"name":"ipfs-grpc-server","version":"0.7.1-rc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.1-rc.0+cbd3e948","ipfs-grpc-protocol":"^0.5.1-rc.0+cbd3e948","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.11.1-rc.0+cbd3e948","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"cbd3e948deb5a6489cd69d1705a0261860c2ea22","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.1-rc.0","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-0LJbwEzCt38nu7H6fljYHl1deFbxm1u+oJdOS4Xk4v6UMg3MzXXmcF3vvtA3rskOCIsSXmNSiqEWs7eVXEEylg==","shasum":"f3821deb5a4ec17209de703ce0c51acf34d37ee1","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.1-rc.0.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEQ9Elr0Zy1ybB1J2nAA1NM9d4rWMw/z5IVrCd/yD+TDAiEA/VVjx2w9E4MI12hiJZT1H0r8Mw0g2rd+ayv386nhqjQ="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.1-rc.0_1632488017183_0.730120805854874"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.1-rc.1":{"name":"ipfs-grpc-server","version":"0.7.1-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.1-rc.1+a0e36f40","ipfs-grpc-protocol":"^0.5.1-rc.1+a0e36f40","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.11.1-rc.1+a0e36f40","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"a0e36f408135c963d4fe3a66ccbe94e60ae5d8c7","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.1-rc.1","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-/E8LuUJLzyoIAwoF6Or0ZM7vloxrcXSVlRIEzCZBtgLP+prQq+H+SocfIKGlKrwP4o4q+uQExBa3zBYKV7cOXA==","shasum":"dc1ebd4156f0b668cba1c9474e2729439abcf768","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.1-rc.1.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD632vjh0JT3P7pp1U6UDbQ/wGinma5h7pzVN65YoGZNwIhAP6FoS9JSpBgwCrLAdiEZGKCnNEIwsu3WqVdXRivkPW/"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.1-rc.1_1632590773019_0.060539797448492694"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.1-rc.2":{"name":"ipfs-grpc-server","version":"0.7.1-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.1-rc.2+78060914","ipfs-grpc-protocol":"^0.5.1-rc.2+78060914","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.11.1-rc.2+78060914","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"78060914410f54f443aad4c5c0de39f899ec6f40","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.1-rc.2","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-o4cM0Ag793yA54LTV/UmpyPPsSczCQlYt/N+FBZjgDjgXZm+Yl3rq9pM8WbyW8dJWVrxdQNADpsxLxmmsUImaw==","shasum":"98bfb4960b8e2fdaa276772404302e95b26e2d90","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.1-rc.2.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB4vbPSXhqoyr6bFIUfiVdrwb+GmmEooWo8SVhHtbSBwAiEApmlWj1bn7+aBkkBzYBwLvrQbiVi1rQ0TAlYlnXj6hsE="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.1-rc.2_1632593469344_0.9376550897609606"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.1-rc.3":{"name":"ipfs-grpc-server","version":"0.7.1-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.1-rc.3+7cb98616","ipfs-grpc-protocol":"^0.5.1-rc.3+7cb98616","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.0","ipfs-core":"^0.11.1-rc.3+7cb98616","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"7cb986167d2e51ab0ce94104bac92ec63c0a7cff","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.1-rc.3","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-xMUogMBE+k/e4GBDIIH0C49wpxIFW/6a++45SPiamUCHjYFK//B33/oBW1AwwJmLAvqvPD7Vk8J9tDO1DZWTVg==","shasum":"59e49f0504fa58d9abf402ae205e748db1281161","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.1-rc.3.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAJBd2XR7VvE0H360RCUZwzkcrbe/1odNEVhq+QzL7hBAiEA+7rPTCAXGHlE8BY51dmuOBe3agjlCoMbZocQ+NLD/rM="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.1-rc.3_1632760648155_0.6870496533640524"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.1-rc.5":{"name":"ipfs-grpc-server","version":"0.7.1-rc.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.1-rc.5+4dd8acf4","ipfs-grpc-protocol":"^0.5.1-rc.5+4dd8acf4","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.11.1-rc.5+4dd8acf4","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"4dd8acf4d7df0ece0afa764d44dbdfbf788807e2","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.1-rc.5","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-Pu0QO9cXx8m/T/8jELDpDpQor94bC3oyTGr81be8M9yc9sjh8dR+b40es7J+0ioUDdE1NRHJG3ugX6duqWqcew==","shasum":"62277d143abb63da395a483da5f48a6d4008de0c","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.1-rc.5.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH3NZsSJa0i4sw4D+l6XKIh5N283NJti5EMiFY5pg9M9AiEAwU+EbZ1ZZQSgGIpSpxUgCgJ3bqrpU3lkf/YBqGpt0Qw="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.1-rc.5_1632830413441_0.8788662528867568"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.1":{"name":"ipfs-grpc-server","version":"0.7.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.1","ipfs-grpc-protocol":"^0.5.1","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.11.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"5ddd0c555cc6577ee15667f4ef4e7f3a3b17d04c","browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.7.1","_nodeVersion":"16.8.0","_npmVersion":"lerna/4.0.0/node@v16.8.0+x64 (darwin)","dist":{"integrity":"sha512-uSftl+JbB1VYDtvMRz5SUrgSI7dHnVgVdVB0oT7iiRKeRUgGlC7gisRuoCXsZiIT295MM/qFZicbbehBII0I2Q==","shasum":"c5d00d7f3b96b280c946d44d8bbfd0ffaf53eb0f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.1.tgz","fileCount":54,"unpackedSize":52837,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDOgl0YVtKtlAPeF2lcQVKRalmR3hn31cB73MEMH6TG8AiEAm2rCtxqLqASP5N6GKOKsKDZK/aVpgNHlY7Fyhwl1bjg="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.1_1632830577015_0.9950677894024633"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.2-rc.0":{"name":"ipfs-grpc-server","version":"0.7.2-rc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.2-rc.0+5ddd0c55","ipfs-grpc-protocol":"^0.5.2-rc.0+5ddd0c55","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.11.2-rc.0+5ddd0c55","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"5ddd0c555cc6577ee15667f4ef4e7f3a3b17d04c","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.2-rc.0","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-4+07a7+CRKMx3k97F4SKPDvsbjzg/vcRPqwHhmVChNhk5q3zSzTOTbv3YbTYgw70/fkpu6Uo44O5/JJAeixtQQ==","shasum":"ed9084e2bf0d2140110661c018f3560021327619","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.2-rc.0.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC6b/SXSJ8nW6yW3afcuCzoxbhUOEilCQ3wAs5n5UZYaQIhAKLiT3mttIHTrbFE+g+0LFXLzNCVkCEdchKW9yptGkI3"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.2-rc.0_1632830860427_0.6573456571101637"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.2-rc.1":{"name":"ipfs-grpc-server","version":"0.7.2-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.2-rc.1+3ce2f769","ipfs-grpc-protocol":"^0.5.2-rc.1+3ce2f769","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.11.2-rc.1+3ce2f769","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"3ce2f7693b59ad4176e245c4c7e75a91dd1bf94f","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.2-rc.1","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-fKR4jyt66PBDoY4rnQFbpC5ygYkkWRp8tFfbbkkaswiRfZ+1Bs2iKVCEemY5ASj32rGHg5hoTbV5twCTkJduBQ==","shasum":"a593416d10f902ad7fdb9bee67638da8469b50e1","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.2-rc.1.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEu7JGPHyD152X9hFe8wFNuCczRF9BVpo3lifCDhicBTAiEAuha8XN0p+b4OzP+GAkxTZAx9lVTiG0p8AMm8kYNX9WI="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.2-rc.1_1633016931872_0.03344142942799011"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.2-rc.2":{"name":"ipfs-grpc-server","version":"0.7.2-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.2-rc.2+b09a18cd","ipfs-grpc-protocol":"^0.5.2-rc.2+b09a18cd","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.11.2-rc.2+b09a18cd","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"b09a18cd98883662353d116a8ff25a3ddaa48fc2","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.2-rc.2","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-esNWxak0hoK1hhthFIZC22ZMOoH1TAOE/c9tV9i8PZSl/VKFZbPNpGyaQDOZF0CMTwmFf3OTrfPo2YAfwZ6TqQ==","shasum":"52b4c4e99e19d5b6e2d4f5c05ec83f0fa503fb34","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.2-rc.2.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH0SV6C1MnXwiZkAH+QlPTEazgl9oWN/Q/JNmDeK+WfDAiAznSce4qSGlctGZ44pPBQnU0KEappspAhJ6zhSarCKzQ=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.2-rc.2_1633023551106_0.7202328749735152"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.2-rc.3":{"name":"ipfs-grpc-server","version":"0.7.2-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.2-rc.3+bb0dd96b","ipfs-grpc-protocol":"^0.5.2-rc.3+bb0dd96b","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.11.2-rc.3+bb0dd96b","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"bb0dd96be3e570f5a43a4f31f43d1c97e8322605","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.2-rc.3","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-6OUIUBrB3v8TaglIdz0/RnPqwGL0jf4qdBISs9tNA4n2tv2xNckB9+1aii+vJ8oOG2fG0R0Uenz/dvzM0Jz89Q==","shasum":"ab65b38fd3575925ffaa526ba04a06b8588d82ac","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.2-rc.3.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFimqycqrNaiJ3LauyG1lvNbgIxpY5H0ii7MfgUEuiWaAiAul7APIGYI6ZXIc9jR6BW+ZbRqE5vg8NCtjzW+aPOI9w=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.2-rc.3_1633179493777_0.3576458446637325"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.2-rc.4":{"name":"ipfs-grpc-server","version":"0.7.2-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.2-rc.4+09c7bf7b","ipfs-grpc-protocol":"^0.5.2-rc.4+09c7bf7b","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.11.2-rc.4+09c7bf7b","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"09c7bf7b63620f84d50c8a3983a5d4c28410cd82","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.2-rc.4","_nodeVersion":"16.10.0","_npmVersion":"lerna/4.0.0/node@v16.10.0+x64 (linux)","dist":{"integrity":"sha512-kPTKllI5DrADYKqmSl3DDVgb1S4IT7B8g0uIzHXs13QUJ4hAZ3KGIPZTfx/sGkXQz1GkGHKM4+3KtO0iXNxG8w==","shasum":"70c94c2e20520a2c644e8860665b3137dc41b31f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.2-rc.4.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB3nsX42aXY43LkFI+jblCe0udXmU1DgvG9MNL1yCJD/AiB9d48aaQVxHAG+oZ/5I/0B5DeB5TjVkXeCAvt+ZvmL8g=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.2-rc.4_1633703580968_0.40245398010585465"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.2-rc.5":{"name":"ipfs-grpc-server","version":"0.7.2-rc.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.2-rc.5+15184bf1","ipfs-grpc-protocol":"^0.5.2-rc.5+15184bf1","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.11.2-rc.5+15184bf1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"15184bf1838956a44c079660a4d82c24166407db","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.2-rc.5","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-zX7n2Rv1sWZrtgekkoBS7Gzk8Ne3R2zIrMBOElXzQmWvfLt/xykV4wV1VgDgkFUNvP7cuyQHUGx/kETdmjQw8Q==","shasum":"477f02ba528f9cd32bccab839f95d601fcd186bb","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.2-rc.5.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD9EzwTsWieESfdJ+74DUARi5zyv9yILhQWw7Di9Ns9mQIgeovBT4ME/F4YpeuatnhCJkYRODoCEahu4Dz+PIFXIrE="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.2-rc.5_1636010777773_0.31907322176685704"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.2-rc.6":{"name":"ipfs-grpc-server","version":"0.7.2-rc.6","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.2-rc.6+8a3ed195","ipfs-grpc-protocol":"^0.5.2-rc.6+8a3ed195","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.11.2-rc.6+8a3ed195","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"8a3ed19575beaafe5dfd3bce310a548950c148d0","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.2-rc.6","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-dIfNKmX+t0VUaNvynI75ntFRHfNpeWHwPGLLDgDrSldQTbteOiIoIPiEjg0IBGd0xVjQXGCIIxBnsCW1Lzfa/w==","shasum":"0b400d6434d9d841041bd0ad1d92c6385ff75ae0","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.2-rc.6.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC9eNK8YIJLt9lBpu77BawlWzpxazd+TB+kQ8obwvCAtgIgNtRAfHqVYv5G5BucXy4VUDUeJoKhwA2R4/xU4lmap9M="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.2-rc.6_1636716673004_0.5599706026434397"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.2":{"name":"ipfs-grpc-server","version":"0.7.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.2","ipfs-grpc-protocol":"^0.5.2","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.12.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"568aeadd8f308cc230de06a956c1a9e6102094b6","browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.7.2","_nodeVersion":"16.11.1","_npmVersion":"lerna/4.0.0/node@v16.11.1+x64 (darwin)","dist":{"integrity":"sha512-33chyliMUyBT5xnxiecYRuNYEszNs9f7SfKbFdS7zp/fO5sDgMmCM2JNED5Ihe7yaTmX0xGXffxJYG1/skmkJg==","shasum":"4b063a0c10d9495278ecf8ab5609b09fa8fe07a3","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.2.tgz","fileCount":54,"unpackedSize":52837,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBxIvBHz2o4rI0BzbSDQjjHfdobyGE7YvJ6hLj62PD8GAiBgFxJezbIoc60YhReCUYc0sUi1cySTr6Yn3rCcR+A6Fw=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.2_1636718053610_0.3294086805709169"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.3-rc.0":{"name":"ipfs-grpc-server","version":"0.7.3-rc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.3-rc.0+568aeadd","ipfs-grpc-protocol":"^0.5.3-rc.0+568aeadd","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.12.1-rc.0+568aeadd","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"568aeadd8f308cc230de06a956c1a9e6102094b6","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.3-rc.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-weWYHkwmsOXGHH0dZFGVYLWZoOahHee6IXz/n5SGxxKc9hUNLgc+l2kkjASDYaNdkfKAQzia+yKHKLmZgrJotQ==","shasum":"9869e85fbe224b9bbd8fde5bb26a68992c8cc711","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.3-rc.0.tgz","fileCount":54,"unpackedSize":52893,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD+iou22XHkIKjWyrjUraopGJh7CDGsZOD5Mq+KqWREBwIgUTke/f772aTbxWyN3Dudj1Y5wzb48UottWv3dqaSQM8="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.3-rc.0_1636718167585_0.24797080123294024"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.3-rc.1":{"name":"ipfs-grpc-server","version":"0.7.3-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.3-rc.1+f419553b","ipfs-grpc-protocol":"^0.5.3-rc.1+f419553b","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.12.1-rc.1+f419553b","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"f419553b9dccc0a1172f399c41b766a754a3ac56","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.3-rc.1","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-DWgRgjfn/6LIRg1NNYCikXro1Nkigngboc+hlj/o9lIYGXL/ILIqYvdBpCdhVcH0JPPuMIt3B6BK/gmqYj66uQ==","shasum":"07af027946e984a50013b2af4bd106d5156ed902","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.3-rc.1.tgz","fileCount":54,"unpackedSize":52893,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhl8XRCRA9TVsSAnZWagAAOc4P/R+rV3gdpwGW94qSxZ6g\nYuOqq4Pt9iiMlyD4Whx4/il6Zoh2rDR3tqxN2183MpQqFFb+PuzNhd2cYW21\nwiMCEnXwhaKc5vp4tcSEBwVmmFAUZW1rCV5gZc7z+sbvA9y2+QyDCIabNGbu\nj7SZT+VdUG2ms67R+DqZl2UECU/sjg/TnfqaFeVQP0cmiwTQ33HrVVvXEVnb\nvE1vk2jpFvYywk4iwxp9Dgnf01hWUorW4dv4dtafJR2QOmzzhjSvjidEkqed\nKTvvbYugeUfW0KWM7Prg1dDHsarr6ZcW8sx5hAHJdSnN1NGxwa/Nm6q8N0a7\nc+DyU/2r1/+LteIu0FoxhxhwpBtrnYj71lYbIwg2LmJblTr9lJULGnc5lQ1r\n9eDz9gc2XDzXrvbNlU5LRipoXutsOminAwf5s1k68uRINO+EFiiEczKi8uJY\nA78OzNOCmroeREX4JESb7N9llKUQxiyca+3PIL8AWXTalWJz+Yl94nxz5KXD\n6UIT0/7cRqf8iUoFwYcX9uqpTrPcCzC5qM3lj1lol8g6+RBPU08g+mpyK0Qc\nGDIkdnG4ciWd9kq5U+CqOBPmUDsz0ezZhNO3v4nqpUeobZYIYPxeKEuxX4Su\nSxbNXswcZXd3KRjNtHnYbDxUqYjad2hYfdmBZvCXxMLcRrtgceTJJBnGABCx\nuTq0\r\n=UpxQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDGzURssEbTPN4x2dGeY03wBt+zR1NJETYhWemEVFulEAiAPvs6tFq7lkKwh9bC2cWz6/ZcGgeD4/nqvPaZ9VQqTwg=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.3-rc.1_1637336529772_0.9098762657340647"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.3":{"name":"ipfs-grpc-server","version":"0.7.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.3","ipfs-grpc-protocol":"^0.5.3","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.12.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"fdc148b5c08c0be49eef77a18259d5baa895e3f9","browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.7.3","_nodeVersion":"16.11.1","_npmVersion":"lerna/4.0.0/node@v16.11.1+x64 (darwin)","dist":{"integrity":"sha512-T+drACpGgjccepd8xD7lYE5wCyRGsa20xCczOIIx7/ga4v2u3GJ8Clt7h9CuGX8Vsx3L8/UZbHO6JJZSGtZzhQ==","shasum":"6c8cd5f8fc248d0a87eed390ca9b954a06f06998","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.3.tgz","fileCount":54,"unpackedSize":52837,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhl8a3CRA9TVsSAnZWagAAOCwQAI/gof+dOigL621sbi0H\nI8WU0ZaD34p3fkBE0kJlfJwHwYPdA/HypG94miZ7mnNVokqv3M3vTQPeQ2E6\nIXwXeKm8G4lFSFdKI219+RbV0pRe8maZRb36CoqCU2kKBLSDzLypKVjXoShd\nk/ebAoVzZm51YWdlrECxf/7b9sB3cUnw+U3A6+ZfrLTJJecKEDl8jZvge9nf\nU2S//A1x/gfbLsdnbvmX30VucjmI0kumbzTTAPJaC1Q6qTwYy23+KRqZpVlu\np5wCZc7FfJFaHlC06rwETW5plDfOM5v17ePmQbFsstUB/pUTMY3YyciPh5qh\nsrhu5JefzNZ49csikEHYgznmtyf5cudvOZ3fWBB64ppYRNbIwPpCZBfLJxxX\nLKtlfmc0291HoNsu86hJgyZ16nFxgboLyRV1QGJzQBohN165to8BgIo8gB6Q\nIXctDcSMe/jy7nocZ0jGps8CPbEhTWaI9LdFTXMlyixSBzgsXGuNTVLDBBXF\nO95VIM9oc7wA9xd1fHjjchDq7vDABFh4MRXa03DxnE+ONRLejCJ/wlGyvXNH\n1oVm/vJBtXACjvveovBPQ5XEcocHyd3LK7vZyJhSzEWgnBtZAw+R2F6a/6AL\nq4mEgQW9K3GTb42TWW/QbYydciAVIma1kdjsF5oA2u6oZHz8aYW55h6DXP5J\nDifU\r\n=0RmW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDnD2u1zLWFTpaD7m2D4xKS3g8NPteK0EadLGPlrjcyHwIhAOW8eRmlAJyky9UIFnnpG+hTVayVt4gYON7mMdRWTG7Q"}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.3_1637336759192_0.10398709492427916"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.4-rc.0":{"name":"ipfs-grpc-server","version":"0.7.4-rc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.4-rc.0+fdc148b5","ipfs-grpc-protocol":"^0.5.4-rc.0+fdc148b5","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.12.2-rc.0+fdc148b5","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"fdc148b5c08c0be49eef77a18259d5baa895e3f9","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.4-rc.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-uahL/Wm8YVovelojVBq97VJaJyaPk6MnaI/v5+OozNV7Nf+VaRcvIFj8StDOuzmxmFI+jFE8LwxIKxFotJRhog==","shasum":"da0d5fb4d83aee39f83ddd24f36328991cd55c98","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.4-rc.0.tgz","fileCount":54,"unpackedSize":52893,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhl8dNCRA9TVsSAnZWagAAnbAQAIVXeRyBd7jmccYheBgL\nfOHkIwB6bnoeDpxy4b3jX9qEkg0pniaTBkqIdPUDioY1VkVWhAi946PGrZ6q\nOMHyJA3TL5QV99HSgapEDzGlV9MeRSSHOcJzy7VUZIF/pouHq8Rbx/AsaW5G\nwaMWsUkZsug0vAvv+rJkPpe1ncgXb8Es4roqYSBFJl5gSY3ws9BeDCpTgSWI\nYYf5ofsBFCL0n3gbMnghL8pbeNfr8XioLsoBEjfM+jqkdakHxyJR03sqgFsz\n6wdiDm8wHT5L8CrXcQOcgkFpaJNYnuBMxlKv4EZmgfCARTvbO8PyQZ2us7If\n00wUqKbtcuGVR3lczeiMxGCUPcVHw4Rz+E6XSRBpTkQ/HX6AZ1rwRJLa24g0\nggNsuNvWTsgoeHiQ8UtU/3V1ZGq2meafnbdtVM8YL56XDl7m+UeXDQBgnWU3\nI4Kfdl5uL5WKzKroni+GKnqvFFf97Ia2/m+63tBfXqjTcynJHGBKb0jiQ1zK\nKuhzM03jf+pPEkbKgcNF+Oj3TJ9o0vhjFzRKtIBy6NNDg5g7RfZRIrTHApL9\n71qzkvrCrreS29sc5kka28oTJUexm5VanPyccYN4PG/W5cojcs0jT/NELDA6\nC4IWUfq6YvUPLpmkQRwoahfQGHNjCd2QAgdxnwlzfDVtA1kTk0t1I080BkKe\nJPJu\r\n=G4VB\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEoOskhAI+w7BmVjzKB18NKVog6SgXMzaAFPD7olYO53AiBrIyprKToWT+4cHRF6DbzOQZs1ZmrVYF8d6WtvG4kDPw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.4-rc.0_1637336909385_0.20972560770611803"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.4-rc.1":{"name":"ipfs-grpc-server","version":"0.7.4-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.4-rc.1+041fc29d","ipfs-grpc-protocol":"^0.5.4-rc.1+041fc29d","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.12.2-rc.1+041fc29d","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"041fc29d151e8727ce9aaafd2c46a4cd34baa8ce","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.4-rc.1","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-oAZCcigVi8ZaGmRvbrlp72Z2hn8MMVmqQshyIrGz8zgF/1fzuqCd3if98nOeVvGq9eUPES6uzjfK8tiR7lCsaQ==","shasum":"dffa4d56f7b039f5ab4c2e0d220aed1dfe8957bc","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.4-rc.1.tgz","fileCount":54,"unpackedSize":52893,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhl92UCRA9TVsSAnZWagAAc/wP/1Rexi9D5NC+RN+MWWmT\n9LpnDpOfY2KaYgf0d3llsjjPoXHlZJdPBTqjZlol+FAEz5KRrzkQY7RWVilB\ne3Js5Q7cTWYV1+TptzGuUw7e4FKsYcjQFKamO6/NTOKI20i0ZL/CQAlWZ258\nATodkE+x/f2wyXbN9Txt6pERHo4RhpZ0N3gOoPSiXid+3/MEUQAF9RwD1evc\n/OV4J0mPLfkmfMjfAkvPwu9to8y31Vu82EmNOQIiQbvwNy+rWG0PPgK2tpfK\nCyEZepGiqH/YqyHZBu/zbkAkKQzx5ePdS7Isp/0IG5k/Cj1dMhxXCq7tYAA7\n4Rn1XO3x0OM/E26RraDIbVFz8tZH48QNm396BuHwrFdLumo7dWjOiFQm+ayN\n95+CCvCuXuJ4KMghpHZ7RGJPTUhSq39OxMRiZMaDVlZ2EoJpPBBU9T7Gsnz8\ngVXMnba4u1b64jjREeYUgE8WMYJ51Q93zeZtv01ic8EwTL5iWzZofZI/mXzG\n4IiBfWlJJgfD0tzTLhd7NxhoU4CdexE0AB2lC0xYfLSh/cnAmdanu6VPwgr7\nZYewtwTpPE9rqOlva6xLBeJkzX8NxnX6Ne8n9wdf8IDFoqpO0t+KThhHppmS\njg2mp6WYj8k34uTwPw+jUDtkp/w+RbwbIjVS/0SQbGUzyydyXttEOiBl17lH\nKQil\r\n=jciZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCLz8hKxFPYEyjDeSE529A1x9GGb72u9DoAR1uZm4Y6xQIgOZHOob4QnNoC3sCW+DnlG/LFHh/jGHrNg8Slb48uG4c="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.4-rc.1_1637342611889_0.7487362638725914"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.4-rc.2":{"name":"ipfs-grpc-server","version":"0.7.4-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.4-rc.2+70c67e27","ipfs-grpc-protocol":"^0.5.4-rc.2+70c67e27","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^35.1.1","ipfs-core":"^0.12.2-rc.2+70c67e27","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"70c67e27d0b82c7650a2a0d7a646afdcd24e73c2","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.4-rc.2","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-4xNfQS8OGtoUM6tkCTtEcT89tVv85sutR4Lq/UnmFwYGmVuimI160RyxqaljOTFB6C1LJEcKnGgWE6G0RIUI8g==","shasum":"5121a9a6a76d1d334db4d52312e0b9627448897c","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.4-rc.2.tgz","fileCount":54,"unpackedSize":52893,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhm8KQCRA9TVsSAnZWagAAI1gP/03naghvAlCO2lE81jzE\nMkFr5mGl6oBGN15XQj/GUiAN2HETpW1vPztxwxgKM6yEzkek760DhNwLgt+H\nXB6Mn8lL7k1b+t+YlVFzx5rUkhLsXdgCVD7xJo7DtA40+y3vNv+z+A/8NwuD\nCW735AXheTR5swWzpXw1f3YHiPMHaVqtSesWrLYBVIFOy6qefgfvOm9fyX0R\n4zYCjxDyDy5OyNucdNXIk9w1jR+9Ud+MRDYRgaQDcSER5H9OxIG/V2N8SJuz\n8kvkCB/rP3763PDpVFdLgB2ijGM83cted0vke/NqXQSZy2Q2cTkmkbeUmlR8\nXMcXJv7UeuTRpMhUFSg6hEmDRnwImd+WHKSiHNM0wRUjmgPCf7MGINf+FS9g\nedUBg/15ammJre1aUVD5KO4XS9L9SPkfralrKxD5Oj7LpMtAyxc3Xa3wBPiB\nHs3+yqAhPcUy4UPZwQrtNueaQ8fmGxwSv6eCHx4f208ji0epA2W/6rc5cK7V\nohi9c1DERR7knxv064zpoO6L0bPbQYsxCPC/GzlE//8+CQcSsPNsCN99p/3h\nRZZ8YjCY7OkyW22+IIYqcFnnLC2JaFVqqnd/szNJvnN6f8G3j3yh4NTrypWT\nx2y+187CK8BlZOLgXsT+g24WGXnpirFaf15L9mITJnWslROYr6gNHXU2k8kK\nDk77\r\n=ja5a\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBqEZvEK0Rds1UFskAHnF3pP37VbR90ytbzZzKCvbMAXAiEAl9JB0SWWE9VNtZ692fGZToNQ7IDBHduIEC/B+pYZ/K8="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.4-rc.2_1637597840680_0.7202426136873281"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.4-rc.3":{"name":"ipfs-grpc-server","version":"0.7.4-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.4-rc.3+484d2559","ipfs-grpc-protocol":"^0.5.4-rc.3+484d2559","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.2-rc.3+484d2559","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"484d2559cfe120f01eb9c5dc728d1f7cfbd89730","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.4-rc.3","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-wSQIhgubBWVFeXbVMJForjM1evBd6SHIh8fDtMVe3zJZHWIfcYZCSvmp4Zt52UwAAA9jSzOfZM+tkKOY2nxa0w==","shasum":"38d8e52cf038af72701473635e9005697cee98dd","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.4-rc.3.tgz","fileCount":54,"unpackedSize":52857,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhngdwCRA9TVsSAnZWagAAdaEP/3FmTPmT3pW9GUtHAYv0\nnMf0S4dhCFwBFdESGJnoOu8A7MlPyDWmokKV3S8EzfjGcyvLl4SeLw9SkEzd\nj4dN/+LOqBVqaNACb5E6WDQ+ldTMaXYNu5+j/zY6TaZUNOJbHySbXYusTGPu\nP+tqGjqdlS7YYlGwDzDKqJETR++DCzyoZdl/Ktqok+pQ5doMoloeQRQZUYz1\n8ZoK5E3pjl14YAogDpkvJsYYMZ5zA0hrhvYBxh39b139Da0KkgUXoAM8d8Md\naQB4tT4sWJ6bou/33MSRu1/cOP3s3h7IDQKmU8XfYJJe78QnHDHuAxP2Sszu\nlNYSKyVi36rHuWecq2pU0ArHEiXLuZaEqdw3ATQ4BKk4zMO2HNEdqn7GwNWd\nd4m/IIovVNrkgAiRaCSbFaVDyKjZdtGhFir0dMiiF3tHP+OhDlaOV4dbPabq\nuGSIP2OYcnLd9b5W2dt4QQRUKxbWPirZnrkf6A3wBwmPHCrLiW8UBghYbCm/\nBFEetqX9tkEmbs4aJ60SJApTf2bnHyXeRRnOxrHF3/1aP0eDIe5Ac2zilP+R\nwh0ICkS5z0bP4UXap5dprBmWjpD3ZHyu5HED5Gvtt5QXp9rpK4oCgs6WQNfQ\n54TjsrAfyLCoouytKDUnXuljaMfWSl/Va973SsPsTFMt8yIUJDz7sT5SVFiv\nFK4E\r\n=8pXU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC+vatD0kjo0Sl/o+9rex+vSZKgYPm/a+WxpWaeyzQEuAIhAPeulicBZvkdHlqE+KYVT7oV2TRcmuEpd1CmL7ffjMRE"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.4-rc.3_1637746544246_0.16600199411752925"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.4":{"name":"ipfs-grpc-server","version":"0.7.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.4","ipfs-grpc-protocol":"^0.5.4","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.2","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"6178708aedf5ea86bf537862c08db49f5b8ea20b","browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.7.4","_nodeVersion":"16.11.1","_npmVersion":"lerna/4.0.0/node@v16.11.1+x64 (darwin)","dist":{"integrity":"sha512-5MstZn2przkzjU7FlAr1fd8gq3bZJvKXftxdnenUlFQItSsoLtKdi2sVygxv8BeWj8xZHETec3t9FQeL3A1QOg==","shasum":"5114bcffbc9e6d59745c5c2ffaaccd7d3afa9779","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.4.tgz","fileCount":54,"unpackedSize":52801,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhngfrCRA9TVsSAnZWagAAJiUQAI/N3tJxmruqjv9Uh/w7\nz1KMz+3ceq4Z/sm9OHm0C407JTSIcj5FCU1sMYtAHUPzoK/yPQMsbTSfjZcp\nA0d86WNxzjJNnG0moSDuAZRQXJzcxwe1u7vY4QThGu+cvhgQua15AlIncbVJ\nxD3Spxvm99+Pwpf18XXQGXW3Ix0e1sWymdUQ2sW0dK956gcDKDg37DzQYyEQ\n+1RwRCjKCEXU31sGynO7dM0AdYlDG1BlRkWxykjYQ/qwnXIjvescDZwp4GZ3\nWhPV1m21t5KAGUo/cdIpvnBVLhhrKKsVhnkr0pfFauKijp1vLMcdprraLLfe\nZxu9B3KQtaY3aAy34sDRT78ocFGUfAB7c7uY2pRMXy3aSe/GO+Tou1GeDffn\ns/vMxlWC3SxpHAE1SO4U9q6CUv1hCl4zd+rHYnrusz8led/qs3rGCEGOLV0m\nqDuksGNPbLXioGpeWHuAn/kPaEwHZX1Akg8qsOQ9SWZ1FNbrG+Wc0iF/HiQA\n+Pe7AxrjRGIhYb4qbvD8VCdZ9aG3Pa0lkYDSu+ZqM83WjYDTJ3ar04WqkBnc\nQ8jiyi985VaJHVHrwGVYl1ihV2hAo4/iogQ9b8P7fDn4rQKglfQ3BSnvtwVs\n1jZtrI+EKVoa61cm2LYJ55rT4A+atUTMzGztVwVefvhedN4aLRyUXvSJhYI3\nrv09\r\n=Xtex\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAr2BEQ35Fr+GjLeZcKS18vfnPdwVu2oR8LxWpBgbM0qAiBzIycATDuOZCorq72IJR/Z7narQz2jSpeC5w7TSiozSw=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.4_1637746667526_0.5779592579071555"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.0":{"name":"ipfs-grpc-server","version":"0.7.5-rc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.0+6178708a","ipfs-grpc-protocol":"^0.5.5-rc.0+6178708a","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.0+6178708a","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^11.1.1","uint8arrays":"^3.0.0"},"gitHead":"6178708aedf5ea86bf537862c08db49f5b8ea20b","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-fCDisJPv/S9NsQOJEp2dz4S0UR7Nw4IU/G312TjxF4x7bHR3mwt/C4u8vzGgRNR+FbC24OT2LwGFieSyUuWIBQ==","shasum":"16a4403b38d49ab5d95e3ee8a8b848e733f1b5bc","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.0.tgz","fileCount":54,"unpackedSize":52857,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhnghYCRA9TVsSAnZWagAAQBoP/AutAuaOAlJpvi6tjNkc\nSz5RJGPIG5P35FeP9iONpFFuT83AmPbSygs3kvvhU9eCoaUoVwnXbFDTSSv1\nVgj6wZNVTO/yPtGMLQzkGZBF8QNyU1FXIC+X/gEidc7yfZf/0Dmlk0tSKeKT\npY244fMD9l+rwS0N8ie0HGds0UHtqM65Zqe+hGO3VKL/ntk+ObY7joefFCEN\nJGIlsPzIT0+41sbPiaURe2o3xxAP8uxyJMn4a61pERhhZG8aAkhkC5vkJx7V\nqsGcbxBofHbFOjjrIOX931LjCe7C1J4ZQPhkU9R4g2mCp5/1Hi4mhdyzQJKp\n4YvfXZ2Cm6wXQMUIBl17JPdJsm1t5x89fP5rEwgpSyiWF8GtlDnhjqqPzdlJ\n7J7kerCEpIx79q8Fn24vLvx8gEqhnEoQOzFGt8sGZwjylEuvUB4iSgyFwEjZ\npmsG6dBYiztH0fFNE6RGuUsn4XFKEUcFrDnjdAE2ArlTPmyzJ44YnRtUiZJz\nMPdo1Ig+pTpfjrpRM4WvSAWdRHpgX1EPF5XkuezhXbSFSs9BavR67oiJSWlk\nyk8lia5V76HyJ+aOY3Aos+wLzglPinLwKaRucC6Wi+yGvNkq3G3va/PYorT2\ntGgxlqBY/dW1uC0W9N7q3RfLq/wmH9IOL0lhVLMOFYz54DReG1zmO0dpDqcV\ng7Bi\r\n=sG2Q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF/jSZJqN57ENhRvImQPygsUXSWb8NCjpjWGomJrkrA2AiEAqgUK7q9iy1Z+WrMV5M5iBj26gPrDAq40+woG7FCAV78="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.0_1637746775897_0.49769244771166465"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.1":{"name":"ipfs-grpc-server","version":"0.7.5-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.1+62d8ecbc","ipfs-grpc-protocol":"^0.5.5-rc.1+62d8ecbc","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.1+62d8ecbc","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"62d8ecbc723e693a2544e69172d99c576d187c23","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.1","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-8DYBQPpiCxldMz1TDEihNzrcQLB8nWHidH5VYnQUug5RJadkbbD4F/Dy+3Z4OLG6MCDVFAYVRnpkNOXaRSBMLA==","shasum":"24c2c4b2be7890c13d8c7cc0dafb1fb6dcc865d1","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.1.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhqfbMCRA9TVsSAnZWagAAlYIP/2E34ZTngkzrxWBZR1pS\nE9Iz7Zzm4P3hNQRerrx53B+DJhPRQ5Jly0P9PVA+JmFvvezlxcpOUNAcakB+\npkbs5NA3CHoLLAMry8iCXp7pmNKOXqx/Lwf/oyVOeKgxatzQvvG7XDQF5bQM\nxKSV+i42zjWEswlvbpoegagzsstfxMKnwsNwN2t89DIuGw2B4v0bnZFQSora\nlDdClUihDRsje5wobk9fOClROcr57q940walw0ICHjJ1sLVJ3l1SVdLMXctA\nqxnYBhTuheCRc+QhI9ImcG8gw/s0CrWPYnaNqqWjmAKL/hqDNrEGnxWS/doX\nc3/uBSHnO8pGtgVH96+gZeXNPnVh3BFoOJ5t6FlEk2BD2ckWVP68PSxuwWjr\nBgPTYTveSHgIDDansG6XbF/4UcSSXRucOkUNpzBtfhNu85DhvxQ3DMqR+fD3\nlPaLktwF2+N7PSMfY4f6kbeFINPP6PYgy18n0BYkGhGIcg4IuNg4tDoJeTvL\n5X+chmslgADwR0nJPEApmzg+6ELUmIrFQ4NSCcenymnh7BObHCmJZBOQKdoH\ndN1pqH6u66XAa+MovzQvF4FUCc0JyZ2oAqoj9tk5R5AYPUWm6LnkczA5Y87r\nXzBZULRux6t1n01AId6JdoxQBNyb4nRvMMkvFwetDSjQVQMca9hXM6qwp9kz\nh8cs\r\n=3OWh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEj61Yt50W8c4mmsRuvkh3BxH4hxiI/+6e4B3J37a1BsAiEApHklMOChfIS32ZJfH+3uaiiXXI1ZgAjYVuEGibrtAaw="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.1_1638528716648_0.6332541229824902"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.2":{"name":"ipfs-grpc-server","version":"0.7.5-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.2+0c269cf6","ipfs-grpc-protocol":"^0.5.5-rc.2+0c269cf6","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.2+0c269cf6","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"0c269cf67a8f6b48809472e83c4c1cff156afe0b","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.2","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-nmSzZUCD8UrtcK9BE7vumpHG5EmCWRNkWohWBw/T5mxiVylUnZ40f+/+MJB6kqDlKPOSeEvqaWoeuAqfpxIFlQ==","shasum":"5d3d95404096c79c52b815961d2c0deb4ccc6c53","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.2.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhqhsACRA9TVsSAnZWagAAbjUP/AwCdNzajCkss8eBuu/J\nKiSdhdOz5qjgP9PhDFz0RvVEU2OCcn2AJHaWwqciSEBx8vC/b1rxyD7FUBec\n9mnoEUXeCqKOzb0zM14VpgzCt3Ruec0XI8EWTcE86Pk4k81aZIRZ3OozMF5M\nh7Yr4i9HtMKtdGhepj2Z5YXM6vgUJTCsNhS8bIolV2iFUlmQcraQQWh1ymDZ\nu0ro43IKP7PSYe1xS7mewxB8V5y4gNnZMIUV5UzBh+mQPyTME3T6AXrpy2eW\nN5nwHWeOqjhr5epvpDX/4QGrGPtuD+ZgYbmFVql9NEkSpQU6YPMOyD1dfUzO\nQmvftV/TLtBzUDPfr/jk1GxwPmAoJnL6PKpUfgqqr2l9OrtmqZ1Xs8NERb4u\n7mamz4L9ZloxdwVMW34VP2RgCwvfoWpk5lpm40Af8cc+6t5FSWHNNMlm5jMX\nrdFwnAEpuTZN4TfEe641Tq2soDRDXDmw/Tt3IX/MHXyp/taNM2RG1Lz9Khbm\nVx6rVmqwGW4N1obkcSQgTpCM7qYb94InhngnI5ZsXPHyeLAohJefD0wiApzk\nhmTo6+L5ZP1f5H0rWFAheE2KoeBW27icgRNz0fbhbuYU79ljwFqMimD03QEr\nRrTVeQ4istfdY7vR8NTw6PUnRnVTnQIflJJK1r0Zbly4FudqXQR3lOssJA3Y\nShLd\r\n=0ZeN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEPa4vmUrKBo9glEyyMP+929P82tsGp5KNCU3tiiul84AiEAztM7jvsldpSUlGz6j83xTZXRm5SMXnZmr/wsjdCfPmY="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.2_1638537984328_0.18369833232865163"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.3":{"name":"ipfs-grpc-server","version":"0.7.5-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.3+38c01be0","ipfs-grpc-protocol":"^0.5.5-rc.3+38c01be0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.3+38c01be0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"38c01be03b4fd5f401cd9b698cfdb4237d835b01","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.3","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-5fZwy4QiWojFFt07gwnbqAUTaS21p9JUmIIMoX9r+un0qjs1daUUnrdvpgEcgThmoEwe6pYxtyS8J8E0UY7XxA==","shasum":"a47b78dd5af73278f08662aac35b7d0e644ab183","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.3.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhqiQqCRA9TVsSAnZWagAAQ0UP/2wvq/0RNyic1kOaqK12\nUlsCI5sG9xn9QBWuxdBQ3tCI2elza5saLOoR1v26JMsw7wY4MN7ZOM6Kd8Xp\n9jovQZBFENwUmRVDjtd3HAZUC19nRJ4yDeUnD/Yf4twjwE9bvcYf4MDCh4+u\nHO2Mr3iDJ5sghttGmOJ6xGrqoS5m7o4N0baVa0UDg5295nB8UcgYSQJxyc1d\ntTgwzadUXTFmSlhqREsm+jH47rpElMq4F4/DS7hyU5BxjAkAk60wKmtcL2Yx\nAhVRxEvod/Rf+ULBHNXiDb8zKkeF3igWdQOvTSCagqvJhgvn8LeHKB0Qmg3B\noFcs3RMC8y/pZL8F7mUX1Jqp5V6uhZrkBIWtjBNN1+61lzjxD0529XXtG2PR\n1GzhphEDxrXSnz99Vd4XCt3UNji7URMzE6fHsSys8hPEBLn15IaDMlagLscO\nZ4h3eUjYEp+RNhu8wl7Ot5en6VLtPdGpf8Prc/QB9w00PvYqFpVlygwSX3fL\ns8/C/3ABJk3Uh0rgV06Xps3qiAfiMl4GNp/obQMTYQR1YxgZT4L0x0x9Hej3\n0t72tLsd5m9bVbDaK3D+EjOhLgjtXuJWi9P7MjDJuLP6V1M/XYZwOd/4ln5J\nRHwTPfuCLDUNLDztEqYT5GK0EZ87j2RDJ8HrmyouTc0KzX6Avmo83MnBgKg2\n5xYZ\r\n=6wl2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAcbaNtFCYBYLqdbShbPTzUwtl5vs/SO+5v6YU+qP6SdAiAz+dwvJPiswkWGzhOQGt4IFPpqlRbUkAIRbsga5aWaxQ=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.3_1638540330243_0.9372841041075921"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.4":{"name":"ipfs-grpc-server","version":"0.7.5-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.4+9018432d","ipfs-grpc-protocol":"^0.5.5-rc.4+9018432d","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.4+9018432d","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"9018432d5dbea466b8332b0a917a166942e40d29","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.4","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-shNejHjnZ/WJ0FcTv5FOgoAJWEFtcoY95VejCPPfes4t6GeHlyhfuURliwB9D9VR3bLEk5FsdIE234vH5yBMwQ==","shasum":"6c5a815647b85425a45c6b22825a8a7037f88494","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.4.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhqjFQCRA9TVsSAnZWagAACBwP/A4Le+tDyzriNuXpcmj0\n6iOJ8YD+A8ucd3az+03RgKFAcsRf0NqkNjoNydH/8WzLBv2sNBr7nqkKNNXF\nDzFBR2kx3DzGqtlLbx8EDi1EVlrNoJKgvjEIOQLUSzI5bR0Rb5KV5DeVfMoL\noafq4VlUS7zzy53+YnSw5zn1cRXVBQZtz4uMR2tHQ3L3Mx6qN6XJV8IZKWHO\nDmuYnx5d/xSKePeOxiwOATUi8MQlYBQRS9bUIk4ScQc4qQp/tayrS1lxTLM1\nQBqpNJZixX89yGG0ve21jcRT8sLzwbsVDQ6J03wEJLG2KCIKGn78lt1gtRrd\nqll+OLuqcwGVSKF07k2TXyQPHcUjQXzhtP4vir142ToJv6+xyLJYmVBCIC8v\nmGP9ChZjSR0pkOKJH71Cr5CGEKTzZz+ZNXCGrTgMTZpWSyFkfZnrNirA946x\n8/00jX/SIZkefWM9uB0vOXcFK77ek8JxZhY2cteH6DWjVedz4+lT/ltl8XJn\n1plc3LNo6SM4VAHeyZut+YCOanSyuD58SywLn72DlAcRCLDaSTWBNDlk4HtT\n5VP5tttVETMQr2MetYZqKlH7+WdZle0xgc+myFSIwuJXpIt866JYPpTKg65P\nddYSYfq5Bcf57Iy5Aygaj1ZEjxtNCEHKGSXERPkRL8g7xSWvnLQGawWw0ImH\nBeoy\r\n=B359\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDcMlN+ui6vlA88OTRVPpZh7Wpeukn0UtOmt1vwOU56jAIhAMVfQ9NfjHPb/CtDLoxcQuR9a6nr3gSwyfHtN0wMcusC"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.4_1638543696443_0.4722101787786974"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.5":{"name":"ipfs-grpc-server","version":"0.7.5-rc.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.5+45ac9730","ipfs-grpc-protocol":"^0.5.5-rc.5+45ac9730","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.5+45ac9730","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"45ac9730d6484e8324acfbc3579fce052b8452d7","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.5","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-LT94k7/GZC+XMU3YOKADuo7DjhVUOunID9Kc1+up86uUFvxmuiKlRgAGkmfZt1IGNKS4dMwEeFpSCTIcsWmJIA==","shasum":"2ccd811b1c50b0c680d08c1f1775e80ce5148fb7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.5.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhref8CRA9TVsSAnZWagAA5dQP+QHKhxhG2Qc1b+ZZPm8b\nGGm0/wf3foZGyXUQUXb1MbBP7ytV+nEK+wk0pfLFNA2mVnJk4LOggI+nqu0y\nmyVNpHo2VHYU7X6dzpG5fcmn8OIu73fN9+NzZE1mGJp4ko+tHQPwLVowO+sM\nWF8PHvg5N9NH18DKJgWKTIHGYtJd/iyCeVzbVEj2lo3BWE686tj/KmPOkjZH\nBE4JXaKzNY1vTlhRDEGf1mqAxN5bJwJLq7mZbM9ASr4dTp2oRxJCuAB3yy7a\ndMBe8uD4s5zEES4tOu9YW7vMimaUYpDSONmFS/D1TlW0WZDEMUTHqu6BdPJU\n7qPCeXKLtq+e9UEUhjOxuVjjbzW6iROPw0fEQKSpQFbQY0M5whtHMTjYpeYW\nY/W1/Nj1bhMXlEs7rbScC+k6yZchs/mrNFV63MJf/CjsO1Xa1PRZ8g/Jgbqo\n+08iegUQZTFHvIRQxhJug2X2bK11HmpLgTfkvY8XliCCs53aBqhLEioV049F\nBcOAB5utgzsfm8xsLYtQXGATzaz6BqAY8i/XMFoAkDMO0+1hJOhkCCogwMjJ\nSg1S03xBwboSODxUxGvHa0GkFnuxO54CdMGPq6JxVPaGoOiCMVYQNhzhOhM/\nmY+gHzFpkfUfOXQVItULZ6xtpp0tUAT/bWjAL9xO0b+kNmha9EUJvP0qykL1\n3AUx\r\n=QRO4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG12ClLd59kyq1RbxKf6/zdjTqnS2q/BIDTA23PWX5C6AiEAu68tooLeeWC9qFSJjQINwM49XF42yfppzu2nXAI1wCs="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.5_1638787068541_0.7446663020151352"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.6":{"name":"ipfs-grpc-server","version":"0.7.5-rc.6","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.6+80ac58ca","ipfs-grpc-protocol":"^0.5.5-rc.6+80ac58ca","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.6+80ac58ca","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"80ac58ca27cc9f21823a23d1e6357f738fdb6781","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.6","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-ZpG6SWbToKKNJeMos3Fia4yS8GyX1sjHNkK9Sx/IVAFeJtJ+1hOCumD5tSkzDsbdCP/MWVNI4PNYqY37S0mvzA==","shasum":"c0c1d2ce222f5d991cf832f87261b988af393465","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.6.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhrjpGCRA9TVsSAnZWagAAzKkP+QGJTT2nNK/kMJQOVzIj\nys43xVsmvHj/t1IiHXbOQLH/K9EDKK0ocgZLNi3z28JdFy77oSypN0WkMl0h\n9VnZDt90IrF7YCNzvo/R3BVMkvM2uPrIbi+jCwEZcQIlaX27ujcaSq8k0xDX\nTtKYvGpSHB84hn/b05Eb457NKEL45QgueArwUp4vwrGZN64EfN2sKeUg+dte\n7KdGBlwWBTgakVdum0ptYwIW/oWpy2r+F/0K0XJgSwMDEpiuVJaOwu/16rwU\nmDndcKT644LG318BEMC3eNV4MPaBXKtF4E05vDMpVPfucfKrN77A2gQCvNuR\nUHGolnULiAwVTD5ZyIA4pbEaxb18/dl/bSfOyYL2KCWMdpKjJrFkiOLPpZzE\nARWyGNANusuZYIDnor5NwPXnVd0Ox5T2nOZ46x3kRnKslazfUq4qeXTte0wS\n/rzwiTYfSdv1YKKKLSoiYm0soqn9qrxvSoeeaKqQkW8ggXG80ykcYxRtLdiW\nybcqcqChmYLzALIWVvRk4zT9Nr03SvIf/lzD6IWXnD0eYn3u9dz8XpXObygh\nPSEyNnyDP0qVQT+pgTHRjXUdJ7jsS3VOmaRGL+o7vs6Z6Th3e6ae5fdWa+gX\nAlnkeAU5dzxXW/C1Gj6wGSodTZsnLSdJfB2BEN6Up/WRNRklu+DY4D8kGRu7\n3nHz\r\n=xdLx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFng7BmZL7J9QZB65vYrCJMDC8LhHGdvB7nuawKuu8T5AiBZsiwnrFCrEi5dA2D/dU39GMvJ/1k2Q8ku/v8n1jMcLw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.6_1638808134479_0.5294978265078403"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.7":{"name":"ipfs-grpc-server","version":"0.7.5-rc.7","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.7+c083645e","ipfs-grpc-protocol":"^0.5.5-rc.7+c083645e","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.7+c083645e","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"c083645ee68aee2fd40f0bd63fc5b4d1395b5b33","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.7","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (linux)","dist":{"integrity":"sha512-RPKcVe2YUIDCl+h1yyFnwvmJLd3YCWNOq7ZFPolD9qx6p68poQGf0GDdh5LrBpC3b0jQhT3EQyQsxryOINH7NQ==","shasum":"beff9a74c24eec7f6618b71b74ec63185310edf7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.7.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhro1rCRA9TVsSAnZWagAA8t4QAJCXhuKKLIOkWAzXAe1O\ng88TL6SeA0lN9J9XH3HwsqYWsGvsFVmNPzuKEtg0AvccS69xAdmMgZmQrXW9\nIN7KIhuU7md1cEy9q2sYOMXPu9Vc1CUZhpvt5hjrZDheo9K0LhmrkmpM0Plr\n5u05vbFUMJXJaQZfgNodBL8Cgx4Zuuf6uZLo3EcK6WaPYxthG2tJMLtYmvPW\nRccyGIhII3y81vVvS23vqVAedRR3pd9nVIg0zR/rWySqO4P3nC0k2ETdk/LN\nKNAe5t8jMFhvLvJR9IQ41c6HbhYmpTVnEm6EbxFL9oQeEdDlUOcd1fInQxNd\nnUoyjqutG1TdabkfiP6+FkFTiimNH/BxbqIxV8dHjpdgGiEq13KYrFenwSwO\nKT9KRVxjvUhYG4OnvxgWYgHgj0axyK3l9gJj/SEltPdNqf9SLcyjqArBtaCJ\nyz0qlNWsYSRhnHIbYAUx1FDMGMXxSIYvKWrtt2wg/NlHnrtKTjeT5pG5ukE9\nEFWLcdPQKOpMGovXH+fEYxRavLJHwxRKgpSqvysNKKtBNljNs7uAeBXVMuLX\nve8dQyuo9yytGrGBPTufkTlRf6ivHVuSIpy8FhU+fynUVSiDLXFzRCFKDrXw\n2rUXL/IQnVEUK5HI3TWmGJeh3U3oRYqgyHhOxMA53kCPvAQyQ5atOSo/h2zW\n6/Ib\r\n=nGQQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGTozY2f8C2H7GPFG/9SweDF481yQ5U8pEErEX9QBr91AiAT9c77s98cHIakeefWcC0iARe85q5vFe9yXbouu2dYiw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.7_1638829419288_0.41191591916613324"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.8":{"name":"ipfs-grpc-server","version":"0.7.5-rc.8","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.8+dec9e4c8","ipfs-grpc-protocol":"^0.5.5-rc.8+dec9e4c8","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.8+dec9e4c8","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"dec9e4c87ca7829761ae6f63a4809783e53ae558","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.8","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+x64 (linux)","dist":{"integrity":"sha512-HWlUYEGarIlhjHoSQ5UuqlmimQ1Kvv1ARc01o1YPKpR8WmYj2ZkrZ67PDgOIlK6qSnC5/nhbdTfRzgaj63u7Yw==","shasum":"ae2faa058dbec8bbdc5c20a1e3b53c32f1746a49","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.8.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhty/JCRA9TVsSAnZWagAAqQkP+wQBiCTxQhrov5nN21HY\nSQtr5Uuc0K02lXr5f4Rcvtv3jF9fin/QdOXXVp/SLbea8v8ip2uAPRB3PU5h\n/00cK2K6G+ohN1z21TIcYIvxhMc1OCdS6UhTIWo8zn+/0smtS1aorwX8UQ7U\nHknqMZm4p/6Pk3CmntMgn3+Fws7oLzxh0R5Jk5PEPfgrjvw1HKSV6GSLJoko\nFNyjMyg9ysjmt2w1rARNU1bH/jyePdl29QbqochUAsssNFFMfPSxi25PjUsC\nuHCg+ohVx5getJ3ihn4aOxATuNEeOsM4oRlJFfBLogvYx1f0F2daO0MRdWds\nM22Vcmw4K8WW+K7+P802YIrJWQ/Qzw8Eh7c+MVMJjht5V6naUVtoorCGqrdN\nI3Zn1aZLtagfMeqL+ich6ciPn5RELqRf4zo5kC6QDI9UgUOkEK28KjGbG298\n8nF+A2hlHLuZig04buBDQEpJe4h+Etx9U2fL3n5u55q8jFDATEOhOdCH3Gfn\nl7apz27FRAZWANLoTTWlcC67X4Hxc6k/Z4P7xF7XKSpeqmlPXYssChnchC7N\nfAK+WKj3aLEzIJshoYUlI474zDEXMIiQMPmoOYEfFFoVg8HiZ+Zk/ZIjX9mM\n9PQwYjQTE3zszfQQ0BvFiIutxjHNQWBt6kq68I7ypgKLLepb6gzGPgUGUAD8\nhLDX\r\n=D/mh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEVtINCZHHn1LDdqcEBCQIkKbK3dmp36SOSgOTpkOiYYAiEA5yJuv5PUYcbhpMt9RKzsG2cuXuBCgYCZ9Cb5d7yioDY="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.8_1639395273110_0.2233721700535487"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.9":{"name":"ipfs-grpc-server","version":"0.7.5-rc.9","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.9+adde8c13","ipfs-grpc-protocol":"^0.5.5-rc.9+adde8c13","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.9+adde8c13","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"adde8c13ba433b81e76033c418607be389fb3d31","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.9","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+x64 (linux)","dist":{"integrity":"sha512-4/KS6H9VNtL3NChwULx2321ewttMAwHKXTqTfgdq4YB9KiTnC4gQZkZtFXA0PUuAx03kwKSqH050R6lcq1cy5Q==","shasum":"63aafe4d2a5edd871c3eb77c4d66e513c15a702e","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.9.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhtzgACRA9TVsSAnZWagAAlQ0P/145IjfLhgjIOoNlbmZw\nhb44/ebmhFaJWruORBwlU+ZFLvpfBxAQbfIgOR7ALLI1c5Juwj/Vdk+iMNdH\n6ea4I6LZTop9m3PlbCKv5rsHHHN9Ru72AaQW0qppI5458eJdQRXpX5hC4Sa7\ntUfKdU04vV0y1nX0FLD6guZMAGzOYsSJkCW7Wfw2Kf8tfgLUpcmeeDe1qJyV\nJ/Vwp8T5YrMPfBNXuSwqu4VO4wmVE9Ut7l4rwBkbayTG61u4hg6O3i3fyyji\nbSevpVbZkS6Q99PGxfpcI+O77mExvkyOeQFlnqzUyPc019mTVue/wG5GyLa/\n8l9e+T0oyosGPC1Fsu3n/CoHp7up5axZatzWxaeX2k7c3k/kUaH7QoOX7nF5\nWxaN3Zgb+JblcYYm+VGQ+xOV3MJK8Hq2df9FRV4yabUxPCRTt4JoeEvpsS9K\nrddom7rJwZ5lx4pyM0owV718EXNlRP6eN6fXsqxfl7CFwsOVTdcSBEYa/0TP\n7scNVFPXPL5SdT8Nx26KVVmfOy9B8hlYS5sR2/4WtEerJ5hSjJixW/vpMzc0\nxbyRqYPHRXy8XJtBujlewkk+XHomz6UbP1rjS3YVOEUlQcuk0wQa8OQGT7Sl\nX+ml5l+cGzUiPlJGtSmLVe12rWcoiti792Hkn1bx/IkNEGh2F/hdwg/8sTuN\nuZtw\r\n=CRGn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDVj9KNVRjJgKmG/BHr4TxOeT9dgIbY2ZQl0ET+FIrVdQIgDNQvFC7+AasGmqx/Qr8Ru++IZ2ejgrYQGzkZUVYf/v4="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.9_1639397376105_0.0675748617494829"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.11":{"name":"ipfs-grpc-server","version":"0.7.5-rc.11","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.11+33f1034a","ipfs-grpc-protocol":"^0.5.5-rc.11+33f1034a","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.11+33f1034a","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"33f1034a6fc257f1a87de7bb38d876925f61cb5f","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.11","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+x64 (linux)","dist":{"integrity":"sha512-3+oXtH68lluJeI6IYqSfqlRLVsB1yVZeYI5BGrtO/TMCGQN3coq8Cm9S4rMAgyCbIL/ozCIrrynoSArLFCk8QA==","shasum":"28ca8bdf61db54584c6c0a8b42402d3d579f1f3b","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.11.tgz","fileCount":54,"unpackedSize":52862,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhueSOCRA9TVsSAnZWagAATu8P/R+W5bmOAN+nXZb565DL\nLXCNXf3t3v2hkN4fsXSm0o7yGXLCJ8OhKsPtAaG7OHPSF9hVhfr+4/Kp8SC9\nNrYYYGkCOCoV63i4AFHENzCMZ0rn3yLNr9Bjrv3n5tU99ObQEteG0J4N/JP4\niTNrOzTV82i0OxPu07AjOKLNHa7yT8xMzkrpjFPwAbblqM4yQggDR17CWAW/\n6kkRewbUHdwvMI/l8gFWdEwe3jBNDhdEOkvBhJVGihiFSa+Y7junLmEtj0Ca\nJIpMigl2Ta5YAWfYbk4yoFamNnCnimvp6gNLHE9+3pgMvUOPlSiJGXWsuq6u\nphQPTx7iS2tPeDmrjNWh7/mP9TR7hdiHvlgAeb42jrKqH17nb+dpO+e/gUyG\nxDHvJwims2Kr4agnjMD4erBvicDdFursT4p4tkH87RMNFsUEb0Dn2LDkGw3e\nYnryWLV88MGPPH0GUkWIs4WD2k3O0P6KD7c+xwDXXjmqLtNJOl8j04ZiPAkU\nLc9JfMiHwNuBzlqRXbcUTQSaL3NigS6oR+ajRASGfqLRyBFVOHceiMUyhZYl\nDGUz+nghv6V1ccPasvs7UbBMEMfOUVFgqPsEzLAdwjoAk/5azO2FFlUj0Bn5\np00uI8pQSMvVFUnIw7e8+gn+TkYOxg4VrIzN3ZU/W9ZGJoYvpkb84ckbeg08\nrIFB\r\n=aO/O\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDA+W4KO0rkhVSgx4Ip1Zun3ttl8cOvi9MuLcadhUIRbwIhAJK7ZQql6G3xvGJJmIXkATVm6PXefkUyzmmax8eKEdT5"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.11_1639572622044_0.14214254621017175"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.10":{"name":"ipfs-grpc-server","version":"0.7.5-rc.10","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.10+73476f55","ipfs-grpc-protocol":"^0.5.5-rc.10+73476f55","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.10+73476f55","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"73476f55e39ecfb01eb2b4880637aad658f51bc2","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.10","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+x64 (linux)","dist":{"integrity":"sha512-U0s+ZqUkle7yl2Eh3z8tyD/jFdHKoIPr6Eu9+P8JI5lMd6XIjeDwvjsa01Bf/Qv0q0FXtv+e+YlcI9gvcRA90g==","shasum":"497407dbaa2fb3f5096771b83253324c3eee3bd4","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.10.tgz","fileCount":54,"unpackedSize":52862,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhueSfCRA9TVsSAnZWagAAgUkP/1fz4hkkYXCvi5k90ZSW\nlZWsAljkpvur1lx452U+p06/F4g+e6OXXnlImqKro3Lzno4oeGPU6/XMqEF5\njNFNDNIqjevG2ugzB4uB9IErhdnWkEFOqEFWgdOQlNDfS1qZ0qNduYj+6Mb4\nAkmHiK3tu5SVFyFvwdPS/MgbDsFPf2GYXDvtemMYODKhRU3MNeWXibO7DROZ\nMr5JifPr288+dr1/nXBKgNcgDDbzlNun9QbsnbtZAxwaJ9WHcCWRk5QK80rI\n/LJPPagLJ0bwhJjYgwxBzy5mUxb2SW6wQcrThSzimcRcvaPKa729XQulL+4M\nNSox/9fxWTLiXNAuA6KFW7/739si/ig9eh2pvEBs+WSb1xmLfQEmxmm+9Cjs\nS8sOST9zGtWa5WUwvSuzs/5XVSgfc51ZTwtVoOF+rCe/UbI4Jajbw5R6MXlK\noAoz8AGCObtM0q8T2+eHzkYoZ0KljF7rzNTQOVCMZfiVCPOFhCsPyC1hsYzM\new9kBe29uKo19akLE//bHwBq7sYCkap0EkRxuYfcXAAfhkDO0xDfiltyYAjR\nP39ooSCyR/6XT3TDev1LYvkpgZelHVWa7AChHqu+PQlEELE6GZZO8dBrkps5\n+nNpOxJpjoylTFGhpXwafYAD1rMh3iLeDCPGSdUhjF2OLchrQPzMwPjNhz0F\nUbWR\r\n=fmst\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBtC8OILwVkgZfoqgR2jDvuIx+q8FxVzp7HehVOSFbcYAiEA+HJyOXQxvypVnvnZJpeQZrfGDHZ4XXXjCGrp9A/7eUs="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.10_1639572639746_0.9564006759536667"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.12":{"name":"ipfs-grpc-server","version":"0.7.5-rc.12","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.12+6eeaca45","ipfs-grpc-protocol":"^0.5.5-rc.12+6eeaca45","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.12+6eeaca45","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"6eeaca452c36fa13be42d704575c577e4ca938f1","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.12","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+x64 (linux)","dist":{"integrity":"sha512-kemOHd5KeZE0RZenTXNTpPYKeoMXLMCaoqxWDMqOL1Aa1m4nSGOkqBpBrI8FwZefo1YTKiJR5r593yC2k+Tjtw==","shasum":"cfc623ab14cb31e97598e3f769d3c3ba84a68350","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.12.tgz","fileCount":54,"unpackedSize":52862,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhueUtCRA9TVsSAnZWagAAUWMP/jdifWEsMUWtnH5soi4F\n31DhtXJLT5lnQfIBgBqDz9z0D6VO+pfkys41NTYFI8HKHuvnQp3L0gG4fLJ1\nMjt6J6qsgbUK14VYJUOs9veBzCSVnP6+Kh5BEHbYLpjWchJAU/4LETEtEGXg\nl1oMDix/U9+rJSmQ5STN92w7eRoCCouYdl1mTugVH/6Kg3IxLdJCEOzJ969r\n73qm58rBy7mcO12PfQKSy+CT/4ZTvmV7TF1P27BEe42B1ALx/11zMbL3Fq15\n0FS3HhzzFVqiJGfGrOGZdZY6aJ6Tt42uymJYP3+mMjD3p5NUJEP9PLV99L7a\nb6KQf2sdAG0f60ba1Bq2KNjloNm7e0v9y0zX8Pfkw93G/hDycQjt8Df25Zhj\nUiScTjlq41YWrCJhAjaxQML9aCtT0/DG19Epx49G1M3qLUE+kTjPzmzSVY3t\nBS5KqcFv8fZKBMJxJIxEIanyb1RwMne24Kc6r/Dma6c+kjWntrduBNK9bxsP\nMEq0CVLtfek5fFBb46SLD52UxbCe4p76o6dGxDPisqx6YJUH8GrrmAOhzXQG\nHQ38gzeHLXF8eRdOxfj+FGvfOE1IwMLRGtGWmZ8UYV5H0PBymyelt1QLpPVT\n3gHQN7lm33X9ibzVLFoFKXVnONF1XJi0x9HeGEWkwqpsQxNIAJPw0tC3Fsih\no8S9\r\n=BBhg\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICtvjRqO19xNzD4Bu/w2kPZEb0yg7EdkEzfUmkhRZem3AiBBZgrRbadMWgZy8J7cg6FlDryRVZxZ15U7ropCJIF81Q=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.12_1639572781093_0.2464140594029891"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.7.5-rc.13":{"name":"ipfs-grpc-server","version":"0.7.5-rc.13","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.8.5-rc.13+d147494f","ipfs-grpc-protocol":"^0.5.5-rc.13+d147494f","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.12.3-rc.13+d147494f","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"d147494f362d38244bbeafbd6e7d76789c7c5020","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.7.5-rc.13","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+x64 (linux)","dist":{"integrity":"sha512-1qpijF1kzG9QYNPhNicZR66re3D/BqNgn0PmyuMc+YNxz0PyfHarKa9zyw5mdi0bVpmQRGuLzcpzOZy3Opk4jg==","shasum":"040e1c6d056875ae17524509763cc945fe704a75","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.7.5-rc.13.tgz","fileCount":54,"unpackedSize":52862,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhujMGCRA9TVsSAnZWagAAfxcP+wSFpZEYXJVI1Q/LElUC\ngvLn0STdIRsjjMnqrqErwghYpxb2+4gEGll1D/WRXJ+IRRIgt4DagXkrHUh0\nnhDfooXV7zJPG5Fcl5pzK0BmgShtbPIwiki0cxmDYS+57cpvfePva8eyqphs\ndcdjB6/sOr+rWWdrErt9LZsCvai9WT/stPRCMjF9hpSQhuB0YUDDl5yFUgr7\nQkFjLD/9c4Lr2LYHtUF4WijVzs9xeenmy/2xH7jkK8U28CooCzpisiTaVlix\nc4EV5cdO3sTypMneDBhDjtcBZtU/MfX5NcQq5+Y+WLLLAqP33KXdvMoQSNKK\nk+7Y8eFS+W/wxaMlOZL5Yzzeg3bPhhdd2vE6d6fIcaGnv5XbFducOBscJe0d\nJ9HqSO3J+UgJGq7K6w3FjfZsmGvmbXozhpm/F4xTkV/LHu4Jf+yBGj1/MWsz\n3kFCGMT5CUDn8AJkhXqLKZvkhqwH5GEq/FT1NVduQOnuVC3vZ53Xq8iaM/CF\nC5WPcAkUHskGs7+99JNJuixc/7TrUM+NjDkqh++07hRJ0lESR4+vuHo3rW19\nr4X03jApWxjXe7bZadZJJ6Vr2luLmSAgrlrxwaSrYd6X/8JVKMiT6U4wzzBT\nuEW4bom7lx+TVJ7CPluQlf+T5UFv4zMA7rpLM7EfsIPuOjs+fKVDEPYUzJws\nUI4w\r\n=pc6J\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGEElL6aAR8bueanLDahyuNa6kAonFaOsJt2wuzELiYiAiEA5Gasv20uLs4NA1ssSYJDe3GEEWgxLBYZZDSqTzyUvnM="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.7.5-rc.13_1639592710478_0.7830564044136987"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.0":{"name":"ipfs-grpc-server","version":"0.8.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.0","ipfs-grpc-protocol":"^0.5.5","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"7375caa8805298fc671ed4080e1023aafe756151","browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.8.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (darwin)","dist":{"integrity":"sha512-1gC9+r3tx8/eLuWK/iAmziHYuBPRzvyKG5Xr0TabFr10XnNQZQI0mMvw/iogqKeU5RUFZDbf5myl7OjV2/Wg0w==","shasum":"cd114cad0c0e39ce411f3dad9058f0908542726d","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.0.tgz","fileCount":54,"unpackedSize":52802,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhuk+uCRA9TVsSAnZWagAAZpAP/j4SSYP4bnD451OCGkr/\nNN3d8eQxYfhV0FKno6FzSpl2tNpNf1T3PUCQzXRR6jSnQQj+GBK46S66TxRf\ntWXxoquXj2NgcHO9/wfugcXWunms72aLt7YZ+fD38mg3tA5ZamPkLxp38gdy\n8AN45R5LUbqoWdu+XsgjvDcBuFF6XSbo4a0rtaCd2eSlNy4NVm4frirBcxkM\nLzbUAmIevHD1xp50ocPFqUY5OKE74IMdP9miiXzOEo9W1pJ7bLyTRHcS+CSy\nAMP1YY/Wt7c6HmdyFRVgfvOlYyVPum+anP7LyP1qV1tJo3rEX7ooo0O0fLdq\nBn8MKfV9ifoAdQ0E4Pg9DYtaWUHHukByp6YEfl4lzC5EmDVduxD6XjDxj9H2\n8OE4V2GEC8UGAtihkBCybqhSy6tjKrwRFm6P8tnPUv7cBYvZFnTQeYC0NDwJ\n+KGuPY/GQKHnd56OzQYxjI8nvYn5ET/hCGW7+yMb9k0h1wA704QuRVRVkBYs\n/aWUFueW35p1lgDemnsAdxv9IA6QaNbXutMHfLZTZC4qmSxPrkwl5YpmmVD5\nwOkF/S8zVw7EztE0OQe4MayXtjPY75yEVEXqZK0y0utelN0uLOmC4yZzJOfO\nd0R/slouFUiJL3UClw8rwSDnMPHpyUWDz6hkUWNIaaj6VT8Ez7LOYrRI6+H2\nVnqH\r\n=HtdD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEObd8jT898EbxLEd3Y8Rq8rLGQLM1Wc+93PrCP8w7osAiA8Z6tZn3S24TbI7WvDMsKZYXBYkwUoQPQQcQqRXKu0IQ=="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.0_1639600046317_0.1603453108942665"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-rc.0":{"name":"ipfs-grpc-server","version":"0.8.1-rc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-rc.0+7375caa8","ipfs-grpc-protocol":"^0.5.6-rc.0+7375caa8","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-rc.0+7375caa8","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"7375caa8805298fc671ed4080e1023aafe756151","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-rc.0","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+x64 (linux)","dist":{"integrity":"sha512-gboC5U59iUR4l1rAJsKqtny2H65HLv86tXc/WlduHFL9RNRAZyRDBME1rE0aNZH+sXeD2Pyi+en8gkFLbN6RSQ==","shasum":"11df8a60aa47ed7d40afedb6c2b2a1f768a7c10f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-rc.0.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhulA8CRA9TVsSAnZWagAA3xIP/1WeOCS18GzXSzFCUgik\nwp174s9eYDJDdB1Qel5E9BomoJUTmayOs+Dp3EQGIMsLM8jCsqwZbQCcDqef\n+SX7AFcgie6MqC8d2he2kDz1h/L8GNLXagn/VAlbaNJW2+APz4fr/Qo66LQJ\nzifOvG+MQCalE6xoaHDQlSCJzcRulrRPc2mLQ2R0KK1/BK3ZHgska8o1MYLU\n+lZWQJ4tOl8a7apmBZMboVTHgr6/pCQc/1yPcF6WiXuofHPt8bxdGeQQhKYk\nEjuLOCVJQ0A954TD4S5kty292jsCE5K3/PsaxrM0YACmgP8L/aHBVF5cTVPs\nn+Zr9Zzomx0JHR+uxOle/thjUp/7JZaRbKfbomxEXGSSFYjHxR5lwlWvSFPv\n35uD3H/7dgtHJnmSEV5f0MzRrcwwdl1kW7fP9Sr9jPM5ZSd3MS2rhkK6H2Yy\n36tDyfP/DEEPoS1baztAU5z1C5Scf4EXSHbCR5/1OVC3HPO14X08PQ1JdLrP\nXarc8grwceP2JHTMVJUjG9fm5rOArtDBC8tB2MTnFKYPsvQh+PTIJX2qSGdI\nEE2tw+qscfX/H0IE3Gi9QkTXGW2DASpa6SuNQfBumRd6G9Zl0CFlNatKca7P\nLJXI00HnYdY1MBZ3h/FeKEqS63lerv2+dGRHrjxaB3IU+zw3/cOplouaZgeP\nl63N\r\n=Unrm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCbvVLU16XsnDiVQwXNgUSrxNOjH6WTD3g0J8hdagiyIQIhANasAcztApPiHIROrBbahh36wOSnZ43KR2XTUV+qsiMX"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-rc.0_1639600188352_0.084973370685681"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-rc.1":{"name":"ipfs-grpc-server","version":"0.8.1-rc.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-rc.1+880e47d9","ipfs-grpc-protocol":"^0.5.6-rc.1+880e47d9","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-rc.1+880e47d9","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"880e47d98cd89d774d707d20bc4a3db8c0d3c5cc","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-rc.1","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+x64 (linux)","dist":{"integrity":"sha512-i/C1wUe1ueNLVWYm2jjjn/qn6g6st1YtO8mfjlgM+svf1/+imBU40gEaD3crOkpNCthNNBfDSEPPUUICt7Gw+g==","shasum":"8ac499c8ba90ed8184192763a56f6998ff5b071f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-rc.1.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhuwGfCRA9TVsSAnZWagAAkl4P/i4hXjbUFhV0UiBBR5yl\nZGDHZITZkeXEMhf9NMAZyAoQNQoDtzW+gbBzbxBWctFwOat1P/C5ulE9KaEM\nXwBuPOB1yXCvvqnmJpLuEIPx4IwIoZIKcmEDbEnCVGAIOZ25x0XgMrFg+sxS\nptDa5tCOXKY0YgvzafWI1v8+tc1KN7butLn+t/wAssbb8/hpmReQGylNCTro\niLx2D8+ZFm0/5NpP92HQGSk/r14vzN04Ne/S5fJYriKG15pMHRQ666xFxR88\nu+8P/fJZQ5zzCJ/h3D+9kXLL7GIwRrvhTx6eGeG67z85nXzdemGLs0LzdE3u\n0Vs7aSGrxXD6fOTOJpGb5R4dNUrgt/ZAHsTw4DGgbIlorkNN3Q7JefIoJvxU\nGmAiceIi4EtYTjrZMtPjNYSqjWZvdXyGTFZHyGV7KbdyVt+v8iINwfcLgwd4\nJ+c3aAKBF2l1KoMnRwTVcDAWLEZ2NHiikx6+RcMeD/7Xe+gdl86uyty5GTd6\noyoBhj6N4ktQhE2eanvMVAbC4AnTmuTngSLxkGJq2syRP2anlsafdvkncHQB\n2WWqM5RYQNercpdf+/87CgN1PWr9rrO0b++2LTjYIVhxWm+bDcHLGhGLzWMr\nk8hqlJsBeGOpndBwCg7HZct0hcX6zjYw1THnNWkWImmyVwCeKvjx5BQpOeXy\na0SM\r\n=5u0t\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAe0Do9aABIBarz0s2JqRcDVoleM1AsDnqKk7kW8/4QyAiEAkto6XqNbeVUYp3N6Swo8M1wU1CuT/8E1DErLJRFTFhU="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-rc.1_1639645598994_0.19728293973726396"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-rc.2":{"name":"ipfs-grpc-server","version":"0.8.1-rc.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-rc.2+45d9baa7","ipfs-grpc-protocol":"^0.5.6-rc.2+45d9baa7","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-rc.2+45d9baa7","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"45d9baa7576a0ac924f3d01d49371bf1a4cf654c","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-rc.2","_nodeVersion":"16.13.1","_npmVersion":"lerna/4.0.0/node@v16.13.1+x64 (linux)","dist":{"integrity":"sha512-ikkweiuu3Gdda+uvQW4WaM9Vx2bhUDnkl0no6KPew31cHnMHuQTcB0dgQXmQ5XV6idRoFgLOhgk8Mtg3RdgNHQ==","shasum":"41ea2f71c2b31f3f128cab2d969fec628b42d1f7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-rc.2.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhvF76CRA9TVsSAnZWagAAeAUP/AtZ3yCXSfuwdSZuauka\nM1KftJFKHcppgmQ1y73u0xfqbdYUKZ8ezD7bCTISHllwvdx6+rxJhyIdpdV3\n1mpBbPFhMqwG2+gWVf3XfcAXS5EG2o9CbOfnUX5LnRbtdUezNww6igWN9mK9\nuIExyg9JkA6y242j+zC0IbU2WBCSFBuHttN9sWrXE+Yi6mzwv1PcRXaMKas9\n1BANqG41WR55MpbA13hPyra/mumrMZV9BJ0lYMGttFpC3HI8DhhTKPqu9BET\nhAjfCs/8wLYMa9+NWcBB+bk5qFJlmMyznyFLVjtR6pS2T8KCJq2nkz5DGGf+\naqM77mo0yzTjlPNTxgzFR3qyuP/twwRcadZBgXL4+dtJ3ygMVwtfxuJQQ7in\nDHnlcHxzlERdQXd7gJv2R5u/IAxH472kbmQFDNdaV9L+Qe85fT+4FUe5+SOF\n3D83/vlMbo8OS3FkTqJryvPG5z4Wz44xV0LCLk3M8nOR0RKAHEwCo+parnoz\nwtkz3AnQabbj92AEOZVR+w0irlsazKI2zVeYMp0WeXOHwo1F8aUKdrNY37mZ\nZR0FVx6spYUspfQTNFb684NRbL9Bf2RwK1EX5W8oJswYfCph3plKHwIVHbDu\nwUUr5LGl97sP8kfshcN2tNSszGcCBCcaepHl7UxYIdUTEi1+jJtvQJcE/io3\nhh9Z\r\n=MuaQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAeTtdQmC3tCCROIjUDl1NqwLc/cZzWP+rP5mDIHwCePAiBdfRiOC3/TjuPHf6XEfbCWPZTXU+AN0zPSBCAX8hW1lw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-rc.2_1639735034220_0.05615142183424293"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-rc.3":{"name":"ipfs-grpc-server","version":"0.8.1-rc.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-rc.3+67a8c47f","ipfs-grpc-protocol":"^0.5.6-rc.3+67a8c47f","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-rc.3+67a8c47f","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"67a8c47f7eb4ca93ea16defc24b1ebdcf4267971","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-rc.3","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-jyT8sXgOj34H5z91q/Ka+maB2S7y0I9wyC8aljxpBKy+i26MycrUUzwYH88mBRpR9ASBAPNXZ6MwaLAYeZQhHQ==","shasum":"65609be74b5ded6df0e5f633fe207ad2801d2a0c","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-rc.3.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh4G/yCRA9TVsSAnZWagAANE8P/iRuZaN9S6svrvh67RjY\nCuvjD0ceFuJ65n6R1B7t3DzFwz4VF4tt492if4eOlV9gnofbgOjPtOO2L4Mh\nZJ4ScOs6XVYh0Pg5huwJvj3wScp7mJLjIT3ajqcErxhMtQ7a36vYdtxCQuHW\neDSQRXraTixNZYir8Z4HLMH1mtCgvJ580/69zVNLfttT8lyhCJFAL5724Q8I\n6APShJUXTYcn8QDZABiKQRoZOMrCOHgNEpqUzTBW/Tv7tNzIs3Ib6GE+n9VB\nqw6gGEjChO3Mh63S8idP0KLTh8+yH7GStMDLyprO7WR8qWjNRdF19I4CFhD0\nszaG6/LrrjTrhqNNEHZtPmNqAwWjdIQoNAYwumi2+VamCGgRCUT7g4ieSLtq\ntnrpHw/fpGO5MxwZdeUWmTvPthrwO/0igI+X2FXHKOlMjuTj1YQjdTjXrl4B\nRNh7R6O3iji/RgSYWmP5IErRCWDwu9Ct+ORdV+pw7QGNP4dYcPqLBBBVG1ow\nXzzkRX2KGH1VEOdyRVnz9AbkrmWpRDCETw6iaig0zu7m8CUUh9+wQWr1HsYJ\nRBPxkJTiZc2YyiUjEwxuG1umgE5gdglwLWwDbjUthMe2c2x0kFUxIK3d5IKx\nScF5H0M5pztZ1FQUt5W6KSPXXDOQe5830wQFIGn1iUDDj5/0xH8Cb6Pe2Qhg\n2Awf\r\n=86lA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDdoQF5easfa3xIDIZoU1bQnXRmxlLS6Mz4Iw/fDblgXgIgCBxGVB461KS7uckEfyOJjMp0I0nNhUWqZsk4RpCQcE0="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-rc.3_1642098673905_0.3069660697164507"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-rc.4":{"name":"ipfs-grpc-server","version":"0.8.1-rc.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-rc.4+902e887e","ipfs-grpc-protocol":"^0.5.6-rc.4+902e887e","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-rc.4+902e887e","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"902e887e1acac87f607324fa7cb5ad4b14aefcf3","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-rc.4","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-m3LEZZMCy3p2jPBML8XJraHF8tot1wqWt4fDv5iVPnvSmt1ObAtAKcuXgdtZoRLpsEpzsVe8im+xepmYt0bEYw==","shasum":"67018f59dfa5834329c35afdf4ae80fa4cf68228","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-rc.4.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh6XEXCRA9TVsSAnZWagAAPq4P/0uPI39oYu/eDXuoT1K8\n0F18TujxgzK3hSNNV5ZhVg2giTJDoGtkSnPlIRFTevA/f/eZ63Ry3FvbxpJl\ngMCmaL+ej4J4UzIbp0zD0fBRoO1GuBjlQRuT55hHd5PzovvOLCyh6lxMoxoW\nY9N5a0WhmH9aTV7eL2Ykzr506pFc8PiHBZnRfit158EeVLlhGsKEiZ+R5gCL\nHDMlxnpy2kthdcS1DsryMwU5OAbslN22jOOICL/cglWAaoinqu2Awsbfy6zT\nqOwFH0gWrDPS2TcYjjtQRBBT8AMkVzvaFnL+qSlPZtb9Km91d4H3o+og8dru\nix4UfeXWLodBPCfGbj2j0/SlsPUURfAXrWKifCAlnLVU9vyvEVLA+EYJ06j5\nXi3+97cUPnjg88BW33v9iL6ZzJaYQXwdNB/T2rLZlN1iUSyd410Sm92NcN5a\nH/szdS/MZQ+tf/ZPeOMNaypljIaD6ooQ/uyvwW61ATy33S3HSHbUlMiECLtq\ntEqDSGBtFGTr5fx29iKct1MM9Lk2lsJDGtedHzUJC8HeF8o2E0mBcv6yY0MB\nhb8UA3fzN7zrSgnuHYsjMfkKNTrrB2Wty0pqJvod4bRM21PZ6+nIgZpMycp3\n8zzHJUM2yw1Nm0KV+D1cUkynzppQ7owV29hf0EXZpVxC//an3kXKvsJMDfiO\nhVg2\r\n=uxQF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGd2jmLIZj7A4OxCtSqQuEtRZKRBUQ58KASJIU9UJGVjAiEAroFJ5YlcGrYm+rRojFMTpftYjSlkYX6sUvTYOtBubXE="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-rc.4_1642688791467_0.6137032607936699"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-rc.5":{"name":"ipfs-grpc-server","version":"0.8.1-rc.5","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-rc.5+b9382bc5","ipfs-grpc-protocol":"^0.5.6-rc.5+b9382bc5","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-rc.5+b9382bc5","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"gitHead":"b9382bc5bc7341a2771a69b2386e5473b507caf1","browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-rc.5","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-ToMLqKTbnxHQyo3KFhu+yaJHcaDWphqlfWxJVAXu41Z+dXSXEO18GHVDoUq4UkFzei1+lSW1QwPqVLuchhcK5Q==","shasum":"b06c66554b64f23da5eb024a032ef59c3823782f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-rc.5.tgz","fileCount":54,"unpackedSize":52858,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh6tU8CRA9TVsSAnZWagAASKEP/2jCazrWlRUGui2YTE9w\n6bptxWTHJNREzR/sC3gECcjWxB0OI2wezrWXRhlpYIgIA26qdpvp90iXUgeW\nDofD85Cs2Z3+5Iaw8RJGmjBrKl9vzy6r99TrNOLrMvvZTw84W9fwVTbCS8vj\ndNCdkkx11OShxWEiS5w+dlq8vMB7NPLLbblh39OAxEqr5wsKbYXQhdzBLYtq\nhGlZFpgBzXljcnq3wOWb1zGFlF/12+110U4sxuTDHn4NSLwr7ns+hPPCcO+c\nnzKdHrWWP3yzVhSawOQI9RMY4bFiE/6xquF1WnQM5kyv2kvcjKKktRhUhc02\nmIaGilhZgx4up2H1ymBI89BOVHTX8LVOzvK0hF/0LoDRHYXh+hofGTUswN3o\ndlSOKGDFxsqudq1IvIqqsWMWwJz7x25LCltkbbHp27K1NzUgdj6NudEnEERB\nE8jak4RcIDLQng+c/mzAgAxI/yJA+orTIACID5utWVQHuwfIn21vTvt8O63y\nKRP6scv+ylSwgu3gB4j85Y727NIBkOdY/omy6cAkjz/SdoJWh2nGLjPdxDaA\nqeUMb8YKL1T14mrIHLWg9NWA8Q5pxS8a1ACST62et/7hV2YmQ9nFRpJWUc+y\nC6M/moW7K6latgG46GpKN+ggz5i9ReoDqsK7NxWomvkcpcaYQCHhBiK6CAqa\nb8Ik\r\n=g+hz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICrGSk3Rp/kcD2vvalBuy7r1uLrRHrdyJ8Y0xUaKLBZBAiAAgxKT8C8e3GM6bDmwQ1eC1i1GTpum9wzicC0zACn66A=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-rc.5_1642779963938_0.45096539240786293"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-7fe0da57f.0":{"name":"ipfs-grpc-server","version":"0.8.1-7fe0da57f.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-7fe0da57f.0","ipfs-grpc-protocol":"^0.5.6-7fe0da57f.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-7fe0da57f.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-7fe0da57f.0","_nodeVersion":"16.13.0","_npmVersion":"lerna/4.0.0/node@v16.13.0+x64 (darwin)","dist":{"integrity":"sha512-20imnDwhIjK/EMGjpRO6Mr2wnHy7WnqA1TC0p4y5ZRza8kd/cnBfEbFNmr/XwrAoMopjIaezBUTTrycqqhB8Dg==","shasum":"ccffedb3de10e63eaa3ab9a2c2bf912a6dd4848b","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-7fe0da57f.0.tgz","fileCount":54,"unpackedSize":52799,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8Tr2CRA9TVsSAnZWagAAjAQP/jmKAoCSTv3jIdieIqjF\n1pZz54Ci9rsmqcN6+eDo9D2Bb30B2UyX0VTtK/lqX23nIJKIeU37INE2+2ks\npufXPg7+KW7Z1ssPrv99C5rnyDXmq3Z7/gYtoExA+7Abg8clw2mv7lXYgJ1I\nlvi0QQsmGKb7lZs1UrmeW9uUgPZraseufwsyYHMeiZFiCVpZ/ekSLecAG+2u\n9L0gCccTbXi7b50fZaNxvOZxzKdwqwoF2gZKSILu199U2nNXLOQmsd1piarF\n7w2rAZrzh3eyzCne6J+29cETmoLDSOTiLf48JnalA8VDh4Z/ykemae7niWS4\nkParF7Ga2nte3F5rFbYGKKUD+sI3yP3iIkgjL7OyLYqY06Xr76mKwZj19Brc\n/1OlaOR7olTfYsflWm1oiF7FjUhKM+mLbmbOLaSabQuuFgsFBkUeKQaKzVPl\nnMT2lY75pRQa032fIq9x8Acc+UriRr+Ol5R+bVHAWOmZ0VcJAwX0q4ika/ov\nRkE1shj79FVpR+A71LtHUp8dYy+35uN4pHaEbGQIAWdsS6n1o8NM29ni7aHX\n9OoiUsa4PloLls68+aXvVxFcH3M/vrUzrc3NcqdvqUDLH5IzI0Ly8V7NVbBu\nM8jxQtZKMMmLFxqiGNvzeqJThAifxaCPgayiEFaq+8u8vZvfwyHIHw+7JGhh\ncbhH\r\n=Mlpw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDr25hu1G8S/b83KR84FQKkIGbOhyQ3irKMeNwmLqJV+QIgF5qnFXidkywWdGjH94MvoVRC7yoCyiRnORrjNBgw1Zc="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-7fe0da57f.0_1643199222033_0.7094196327476441"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-5439a0e.0":{"name":"ipfs-grpc-server","version":"0.8.1-5439a0e.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-5439a0e.0","ipfs-grpc-protocol":"^0.5.6-5439a0e.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-5439a0e.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-5439a0e.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-QGDMNXzIzOION9+DYm/JHVgSzN2lhiJhXhTdsv7UzJB0o7SWkWOjfi59iDzZQoQ8Lgu+Z3Kr2+gK28UhXb9Exg==","shasum":"3da765e87331f4f3a117547cd155e939d91a989a","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-5439a0e.0.tgz","fileCount":54,"unpackedSize":52791,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8UeSCRA9TVsSAnZWagAABJcP/3XW/BqVlqcfbWiCRTM6\n2LHmtQsLclkmGkTOnd4t8YjTWNGYAmy1UH6Q1qIDlGcqhNnNC52VDjFyA9NV\n06uD8bcNP7W70QtDdHcVggNMRlxQbfyCfWnpT5V170/R6L0Lr4TimYIZrWzM\nnBA0ns+1qVAXAJ0Xi7mVr0OAaTpfWc3y6ebkGH2fg49LJ8AIcPaZBaulbr9X\n3yzQZvUiBC6o4Pu05FOKujea/Q5T5cyinCAeBFbo1OpIUS9qvdWFBJowmYTi\nNPDHCzOIHfqZbgtuVgxb2SYeBz35Wg6hafqHORJvWdZ6JEwX9HE3Ew3w64PE\ncnENq85rUmro1HUFT29m8VVBdJA2VYCC8iKtvah6BThMxgxLDAYOWzHctDgb\nQtKTg94kdqNmqPpj0ZGvz63iIJ3nGnoWEXhXsy9l4+Fo6C5xISi+533tYQtq\np4zlBaxT9LLRzxSuQI0BIIlqQ/BKVryk7ln59iXftz2stR4zSHhc2Rt+wtI3\nOY31dTr+F38brdo0I/5Mu6uo6BnG5nxGA9jKLumHGqvevYMmZWrSTclb7y0o\nvwm1xVPIZSP5xtFpaXkTfl1XD16hgBb1Ke4mSinxkJ4bDycv/kc0Ut1VbfUz\nzubJnr6XfNLojJmdK6EAZNahxctsPERnm7djuyCPtKTiO1wEp7XNYFZLAneo\nIhyb\r\n=CMp2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCeVMLmwzonFa5lX2+GJ44LHwW5LTN9T4StPDuQeLZNAgIhAKzFQldQJdNOz/nFZUMrbDKgVPSMQ+b/GSdEFd0yRTMY"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-5439a0e.0_1643202450723_0.42637560740428326"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-a6b201af.0":{"name":"ipfs-grpc-server","version":"0.8.1-a6b201af.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-a6b201af.0","ipfs-grpc-protocol":"^0.5.6-a6b201af.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-a6b201af.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-a6b201af.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-9k5Ir8Ol09Cn26wlEvmu+90JI8wBCbew2mh4KqzrA+Xc5qWm9yOBMy8YBWcmXg8wHV7idd0aVJZrmi+RymtdWA==","shasum":"747cf21fba11a9a6a6ed41c2ca10ba00d0c7a882","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-a6b201af.0.tgz","fileCount":54,"unpackedSize":52795,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8rwyCRA9TVsSAnZWagAAZRUP/2NH96U/JeZP9DnYWTwa\nMUuv9QRo33XhBbsVvDVUm4wV5IVGTVS5BQIZbVaVoGBnb+VSB6jEz/9Wk10h\neb8ErDNOtReMhS2kHoJdOdZnW4oiwypE3SWHsYxphr/QxSf8wUOx6CDBAMns\nnX67GtxsL5JQmM0603YE0IpNiKjN7YRiHohpmhv5w/lBhBpTWMqvLnl5RKym\naGlG8jNs5CniIgrKOQjSrLCo7muSrQ47a4icrEJNJlYgwd5SBvs8h6ugptqw\n5NI23DAmnWk/CG6RXy5OOMBdKJFupQykeFfcf5OvYfmaIBhkiB4yLKK1DaoC\ncogb4ZXuW4RRQvJqUw+2tfql8TTEstEYzfiIczOBqGjn1mZiC2kaVUkSWRXu\nTTPTyzYJaJH0c0yk802NP12jl1Mrmae7aXUNmFuEYHPtQdEOOxXKSm+TSfIk\n7uH9lKYW/0cLLaucD9Ofsd5py/N7pwfZyZzU4AjKb6/opJzM+FI7DYrKq5e/\ngtHTEi5ngJ5qodEbC5yxeKtUVyoodh9yZl6ITwSlBi71rz+Gupyvhqc6MFsg\ncExrDCnj50puT1GfZXmfy3P+kFIQnFpYhk62SZHpM4BiuP7HDcp+U5AAmpkX\nwAplEQZ+DbclHOFi61ikLkmPlCSZpf8pv90gQbNJkqGKHnecuRaNiArimzwT\nB+Xr\r\n=QDJn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDWTsG6B8wmXMaItLWpemTp6y9vnvfYxi3bCpfrsxlPEgIhAML7cWN7tJNe1KBTpnGxrNp00nsD1qpWrc6PQUZaBx1R"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-a6b201af.0_1643297842266_0.8412048295045402"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-fbe14923.0":{"name":"ipfs-grpc-server","version":"0.8.1-fbe14923.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-fbe14923.0","ipfs-grpc-protocol":"^0.5.6-fbe14923.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-fbe14923.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-fbe14923.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-yxCLDfs0EwQ3qMXy1AC320GhzHYi66a14nPocDLWTnB2Zy7xjEeFZ3kuyxUGL9Fe2rx7/ns0FQcRO2g4PnsUmQ==","shasum":"7fc58a2f40ad426c1f35883b49e5918557d1f12c","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-fbe14923.0.tgz","fileCount":54,"unpackedSize":52795,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8uG0CRA9TVsSAnZWagAABogP/088ndn0aT1Bp44V1ikF\n4zcDOKdR/u7qAlQb5nbL3Sd0+l/Q+zxtdFBgYbkP6ZbpqAAldXc7sS0lYgKX\nB8QAXB1HIfKgSrwhkLq/vGetWO+UpycUcD5T4z8PC6gfnltLccmvkutK2Twl\nrl6cyt+kxA+2bgYBr0m124E4j4G9/D5g5Sv5GsN/SpabzeKtX/w78pPx7J+D\nAXcLUcivvTPpJZ4Ueep+S0YfPRXLgtNg7RhjBQaLvQPHIE3aUqHBqn7be3jb\nWkYrNrUokQO7fSo6UuOCGX0DkKVmhl2iP64i2Tw/h84LEeb+sH3xaxpNlgiI\nsNi3YUYC1RgmtAp5ddXMU8WUDlA9Nr9ozA0wAnRClS833KbgwpTR0BuqyvEt\n0IXK5uSLIGpv+6nkqXuVd+6XdBEUmkND4IFGD/GZhkv0uuZm2HAGVf+RQqsc\nQ3v31JkeyH0Z5bGolWokkScpGCTQU2sxHpevNorVhqSGtvmbEllRYwR+MLxI\ngbn2ShA6c5Hb19G+P79j7KW0vvYi0cSkFPR/34elCR7RSXbyYhNGA4H4280/\nDSe51nC8qsyY9MBjVL477+DlhaHhGzZSsUrEPcA0pqSe44JzQFDet/NizSVh\nupvgwRFIY2cArR3IfCmPLYEvq3IIi51QaFg4xYh1sVFxje4WYvL4j4Nm2Ol9\nstyA\r\n=XFHr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDKsk8rgcN5AkozerBaF/HZJaqZ2sJawr31SAIWgj7JZQIgOy3ZSdXO2jRpmAR2jakNIUTHMFuyeXD6VYkZHZ9sDL8="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-fbe14923.0_1643307444022_0.06299076447799701"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-6cb3a87e.0":{"name":"ipfs-grpc-server","version":"0.8.1-6cb3a87e.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-6cb3a87e.0","ipfs-grpc-protocol":"^0.5.6-6cb3a87e.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-6cb3a87e.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-6cb3a87e.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-vDyzlEdJ4F0mN+2fhQFfUooDll4eM4XQZaubqlrRJhQzVgBR39w1x03oKrIkeqheoCFCsrMYTYHwGfD7jBgb+Q==","shasum":"f3d9572dee74f61ef0040a0fc3b1582076a720e6","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-6cb3a87e.0.tgz","fileCount":54,"unpackedSize":52795,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8u6hCRA9TVsSAnZWagAA17sQAIHGNtBiFzkD5LIi571D\nPP3oOoHKf8AKl5Fsa9/7ry7fAfu0gjkHQFwY9wv1jcMTqr+73XOsTWCQxmoN\nr3Ql9Gux3+MHFXmobaLM5pYgpOUjYm/EUW8tJpyulIq0yCf6v2RAp33wPNj7\nap0ZAIf+0X+EsVpAbmz38c23pQpzmvJiEbCYSCFoehK0DqERgEArQF6A+K9r\nc6W57Cdd1LCwNOsj/5w5L79gvdaG9HH3+oleQRnzdacImjwUyz0UDmySiTSz\n67est7sKGzDJCbqZqP2Z3YVp/api/bBdPoW24WbkWB60spmQruOqU8nfsdXo\nEGAqPDN1SyatgRylGDLVPUwSMjRLJ7+XimyQ0KYWIYyPuxNz2yPkW69eQeuG\nr3HymQqyN+eKUNvfzLdoKCwumrtE3cYmpB9NZQ3MD43jjij9YJQgKrH9FRM4\nDCoJ3P7qio5pusL/JAtd1dLRdWF+kohyv6HpDMwoymGjNavzhHsI3USufiJa\nGQmV4VPemvmhXGiMcYqwkjeBWB6/nhAf9MQFstvli4oAAyur7E/RuN9xz6Fb\ncCLrmr9OgH5OpuAF8oqAtdbQuh9oZOX1gjbZy+b6+mO+Y8qO6ZLOmpGOv5Ld\nHBBS15cTrSls3pCAwWfODChekWxeUf3+Bsao3urTvtuwCoUO/hnILKVn43c6\nYHJV\r\n=8wR1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICw3xJNopq8Hbc0FdyfMa8aFqXbDeA+J+ae64/NZfnW7AiBxXzUJjuRORHksReSIErjKlORaMpJIo+avXyAGE+lDsw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-6cb3a87e.0_1643310752835_0.5463619607919179"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.2-2afef2eb.0":{"name":"ipfs-grpc-server","version":"0.8.2-2afef2eb.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","leadMaintainer":"Alex Potsides <alex@achingbrain.net>","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.1-2afef2eb.0","ipfs-grpc-protocol":"^0.5.6-2afef2eb.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.1-2afef2eb.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.2-2afef2eb.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-o8vcuolXJfbPAbDKvoyYY23iVJg8NXKJhMKEBK5kErtuqFetSjvmY3jV3F+0Hb5WX3TrDdHwA/ES+O0NAcf8Hw==","shasum":"f099173bf9a522ea3ace03eda5a3c17d337be5e5","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.2-2afef2eb.0.tgz","fileCount":54,"unpackedSize":52796,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8vvVCRA9TVsSAnZWagAAu8EP/3FALL/3IOkYunyZdpwY\n6+ugpJ2WnrvK1URzHPCv/VnDvuwF73DjB3r9xVFPDpLfFSS3aRTcT2K5elbI\nNgxtMEZOiXY+QbvN4XfByOrEXN7cTf/c2Lc6LQxU9tdowWVr94yt7ggJvnjq\nQJE+xIM18ZvIayvPC0l284DFwCg76e3mO+8cAhAgDWgAAAfoBrg4tsVDPdXf\nfMFOMvdi1vxkTpyby3X287AgPnRTEb2U70TzyzkFlJHJt5TX03BCBuqrbVGv\nHwfM4Rs/uxH8M0yeo2m/Og8KLyDyZyVvpXhunnpdWE/v7YiVLP4pQjhW95Xy\nLLX+t5pW6CD0gEdCv2BLxV5f+XAMV+rCxiltGpJ/E0KQSot0w6XYJyWQ9bYY\neUJGMv7GVMfj0CGjowbK5hPh/kkA2qQeogWDtDVW0/kfAeE7d17CBgnDn87i\nbXrAsgkPP3K6Cgs6i34WeZxExbX+h1Le9op20byTVCl7B0Wn6aAdQBVhPbpx\nOCdOkRWFqExseUbYbkhUrbP3fYJiIeZ88YahDm0A97/oLojW296TrNDSNfpq\nSX4ZD247VY/EkpZ1DPCvvY4zn+0kEptCxDYkI2wCUJRTy4bForHaUucfBfi0\nGK+pK+weomKfrXnqKaDQNmePAmSk8kv7H0q3C8trbDiLG3RNvVFZ1RAGLifS\nFb78\r\n=mcyv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCID4lgtoqk5PXmeR96qJ2/0q8wSOoduqUwIL0x2H6eSROAiBG/egNA8InUqBiiOcIDjJiJsHtfkQ9Ccj5XiOL8dHLMw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.2-2afef2eb.0_1643314133809_0.29266519954394066"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.2-3a5d61d4.0":{"name":"ipfs-grpc-server","version":"0.8.2-3a5d61d4.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.1-3a5d61d4.0","ipfs-grpc-protocol":"^0.5.6-3a5d61d4.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.1-3a5d61d4.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.2-3a5d61d4.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-dRASskVIaZg7Iopm3+p1qmJs0CCqBUZ4OMRY21ttCJ7PuKZsZDZr/vSWtq39ExB6TgjryMjiiIH/xE35teCcjw==","shasum":"87ebb5378105eccac69c2e552cfca4dd59d04ec2","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.2-3a5d61d4.0.tgz","fileCount":54,"unpackedSize":52736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8w+xCRA9TVsSAnZWagAAOfYP/0hmr/X15trbk3moGTMQ\nY8aqsjbbgql8K9c08OO73sD4GUy/vLQfsLiLV4mpZbqwk5SlvAq4Si9+VrAP\nNjrf5w34AVM6dLNDSA+08MV7LIqu6Uyn23EQ85UIzR85Y4z9Qx8Cb33NhGBL\nhp3Z2Qoo9zUC6mloM+HB59NDlU8QUulKgjlGEkefYRM8avODfbT2vdpMez5r\nJskwFQPOwpwcV7PN29HbhlM9pAlkhefKidBEb1Of9NHcq0IRh+AuS3PXUhYh\nkD53P6OdX/BtChoIHizSIWNHzsVNB2ag+3ADtqhf4dhz3KZcLTGZGGLc87Jg\nm2SVQKqrWQzzYQSA+r42B+oyfBfwIvXgu8WYtcWMA7UAd81zAvRgZDVA6VT1\naf6Ow1ImBZsI3jjM4spflX6RnBwQ3fHfl2SqKMUgHpUcLFSkwfutlW7Kgk5j\nODrStBInoy1TzNBqo/HHkV70szYNWyFLIwCS6MFVjDGyNAqIZ54Q3FaCA2KQ\nKaiNySK5gM38oGtboeq5jVV7oyzV6dKDWZpURTjtgfhEDm8qMmhXKq0DSGCq\nnfx3UY4ZPC1M4otwfPRf5RRZ3FL/L9xnO5h4XZUzvr9L3GFkPUyuV/MOCmco\nQ+CJO/91iD0WFU55eYH/Dwp01XV7KFgkL2aCL6CPb4RZOzKrehIqLdqJ9mu1\nr6kH\r\n=6HsG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCykv/BqBCbwhhxqumQRci2/FjSr2zptP3fnNdc/HsLDAIhAKaa3Dul8oUOdk4zmxJyHFIcsDY4ThwK3+eZAcwujohf"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.2-3a5d61d4.0_1643319217708_0.7656939489402526"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1-cca6e321.0":{"name":"ipfs-grpc-server","version":"0.8.1-cca6e321.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.9.1-cca6e321.0","ipfs-grpc-protocol":"^0.5.6-cca6e321.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.13.1-cca6e321.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.1-cca6e321.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-KYE+ymud3ZysIfJ0sJcs34yU0WjU2S5sL3QSufDELxckD26osLzbafP7SI1B+vSohRApYWCB4xH+OeZOXizfjw==","shasum":"71c3b1993ea8bb9bf26e277dae3dfff76b95adc8","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1-cca6e321.0.tgz","fileCount":54,"unpackedSize":52735,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8yTPCRA9TVsSAnZWagAAe90P/3OBHS5H/IsZvgJD7ihD\nJiVvZ3FnD0h6dY67uLpCaBurtv8/I511RmOS+Dw1pnIZwkTtJyAnjg4taq4C\nScTvdtrj5bl8E+AbQKJALMgbf61F7pSBuCvEB+X6Gxci55COTx1MZbgrAeUn\nG4mF0yxgGbqrEb4P0n6E5ZoOJFyHCxBR7xsfuzMj8H2n1hgHTEhT/Mcq3eDz\nDyWqsky/w+3t4AA34nl/pU8zBiwhcvNj9cpkzlcxlNEaC2Av/rmYwAXzxP0t\n/URMELvwxqLPUI4zaBx0mpdSIFXtmst3siayLeep/kmk8UO3FHaTl92GLotP\nvW/z+fXTO+YLqJwgpWFW++DUGFh3mwSVxHDYNjL5igdo5AeQY1miwLxoKvVC\nARt5qAZ2KCU6JIhY0Z8gWWyxTviZ0jumXUTPTnm/RBWM5182yzYCQJqlGOCW\n1exIAud71jH8OcFHkXfjjEa+hgzueQN1YUmz7ByMwWN2tfUpO42d692/wURk\nQ5Dfp7ulNPuL/nOV/bLrhmq1X/SDQ4mJNLtRTv1vROXFq6QPMrZRisRXIgC5\nAamebrB8LvGBWOvoyiWmh7TvyWYaHMKa5/Tv9jNpoDpDDzFrEtuG+iRZFxth\n9MTcxs3M4DHQxvk4LgiPM2cTuOVVFWePMIadAzRtClaZkH9KmAE/M4FaI63Y\nyggx\r\n=CUSV\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEfyz9jjw2QVV42F2VTlXh8R6MDmHRMOi8uH20C7J9Q0AiEAgwj1Bc20QLCkp57CObfNLFGzhqWyRaXG9kIoq1z+L2Q="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1-cca6e321.0_1643324623118_0.7881719451226883"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.1":{"name":"ipfs-grpc-server","version":"0.8.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.0","ipfs-grpc-protocol":"^0.5.5","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.8.1","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-q7oiFd3IFsYitaEdaQwQYTmZsPn//P9fL1sTCCnUb0kMzrNX9gWG1JSqPtRZuuLDEhO/Lb8Ohg3eRtMGQHBcuw==","shasum":"c69296c6cdc892055a44afad1e3907f7bbf7d548","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.1.tgz","fileCount":54,"unpackedSize":52692,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8ygRCRA9TVsSAnZWagAA8s8QAIvx/jmqSpAToK6WG1Rn\nLGIXw8Y3YfnIEvhfobI95QNHam3VMpJvWnmEBRZxM3oIuwvxwudE6fEDrGOk\n4VoUk+/zmKXTBhqqa8hc2qhkt+il9iizEknIPlad9lPDM+iDXVvMXuOaev5K\neziBvuOJuS7avAwNhbezEZS2XZ/M7DYuvBtO5hG4+lHPTe4HRADaS85xsf3j\nNri2wvlqVGp+lS/w2o7CcmtadC+8lVYygtx7Q8DIXrh5pQcVHzPzWUYTJRRB\nmNAo4Uqfhit83GkcJc7pYs7PEr6nhwkShhqBG/8vHLy0ptL9k50nD3XdKK9c\nKkzZXAjaCZTEd8CL6fxmrulYt7zJ+VhozpPkAY18ji4kznFBZZT3QlLb4/6W\n6jlbBY2/IhdNLugmy2ekAQ92X5NC+EdZio8DeMBgc+zSkTjtmm9djdjDaSI/\no1tPRnP4pZFyAn9iOebHxtb2xR7Ex2WAqA6QiBvaug50C4xRAZeKQEYuEDra\ns6BEaqnx1hH9tiV2WD5au7itUadMwEneONR76y9i+eazSmkuopGMQzXvfFLd\nyTz0Rv34SKI15cCKRJ2eVMTCcAwK7HckVC08WTjeQTegEvT192nZuiDYWtOn\nRtJukYUtzpquPGALULr+BEoQJbF8ZuHvBCOcnpYBREof2r3R94tvkUSPKraK\niiDy\r\n=jjv5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHDjp3iIIZYHH3DXb9daSs2ka3ZQsYKIiBT4yw38UbsMAiAFLb0eodz6ZQ91oYD4Kmx946/hclTMRn9RNa3BLXUPng=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.1_1643325457779_0.7236960448273924"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.2-8d260215.0":{"name":"ipfs-grpc-server","version":"0.8.2-8d260215.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.1-8d260215.0","ipfs-grpc-protocol":"^0.5.6-8d260215.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.1-8d260215.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.2-8d260215.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-CqJyHna3l70M6Mz70y+GK18X3U+3XdHLxh3iQdP0GKFTKgqZC1kunCtoQyrCgnyfeiBZDz3tavbYrWAJSOWk9Q==","shasum":"45a846202f4d4bea71687168590123d5eaa4220a","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.2-8d260215.0.tgz","fileCount":54,"unpackedSize":52736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh8zBXCRA9TVsSAnZWagAAo8sP/0VxUN1xxj/b+yGQ0uay\nrp8uY4Yo6fT0ZLKf1cGXad3NW/66EUXY74QGbmtm5BfTmYoyUDMk/df54Cph\nWIbzj1kXRxE8n53xiMEN4Q1DxCIUF3Y/wHKW71FZFdn2joYRe2I4a0Ai1ZLi\n/wruwarBaoXdJr+cBUOQGJtjY7fgao+50VgYBpsnzbq6tLQRaokmGhj/xzu6\nccVCUAvLB44ukQT9bpfQZ/6kKsEHRuKDMluz7+yjNU9kjnfxNVPfI55ffGYu\nZvltc/69wQwlah2i/Il9rT0k8z2ilVZGxB751m2LA6CTusGjkxFv1dINzP6k\nibf6ozVvf2NMGWfSj912DuNZbbQKsbNgv7pFzsOhcPMKuLbGmqrfaxrPhbXc\nmfdNbsFyswzBrXvbyvS8PnHyT5az/rZFw/ANAdFEjIt1l7A2TMXQI3xIWj89\naT+DyibtvGRyaNQ849E0p/52fzp1rnZIXBRDtt4XsKQK1mXQo2j9sxW+6pvD\nnSdw/ayODmgQonQl+esBkE5IgFDA/Y6K3GQCV1TCaRJkLb0dw6z2ZEcF68so\n1A9LQJvmPFCEG6JgtfC4ElP5i+cv0v5CgwcwasC4y3JfXj8vzJtjxCK/1biN\nPsDqZ+sHD9B5pbksyA43qPu19nqJfPKmqWWYLsVrwUS3+9Ck4dCFUuPVTSjF\nKb7P\r\n=KRtZ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF+suSiQcdtVQar+Z4+jjbEhBIAlUgBIxvDz6PO9uPLEAiAjHcCi8kkO7IEmuxLaBAwfA/ZO4e0wKL+2UnvoIorexw=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.2-8d260215.0_1643327575136_0.20360726031638032"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.2-2c8ec080.0":{"name":"ipfs-grpc-server","version":"0.8.2-2c8ec080.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.1-2c8ec080.0","ipfs-grpc-protocol":"^0.5.6-2c8ec080.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.1-2c8ec080.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.2-2c8ec080.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-7i3dYbOPzkjeMlAIHGl75lYqF2aOjMM3d1L20a4rOjvufbQhC8oEDMRWgL2ewhP/Y4NPIcY4I5Rh1hUheAZOdg==","shasum":"574d3d49927f9fb2de55af37f425808f8912f6c2","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.2-2c8ec080.0.tgz","fileCount":54,"unpackedSize":52736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh9AQVCRA9TVsSAnZWagAA13cP/1PImAv9wZrw3V4rmTxy\nOOAJQus79K+utC0eC5E5gmdISuXLnZQ69EvSvANucw6aO/u7NR/CtEQCPqzn\ngs7YdK2RfA+lj/nPkQ6Z9mDlZAOwojbvyQ5/8UshIt3GjunsAPzhY9bmehds\nXyvwu/1pYj1l70w2eEwl7UXIEvgXs0fDle+zKyPxxdmDAKH80ArY4pmMf2SA\nZyrJZhmJlffZzW6/dSnN21TTcgyhGtUvzkmdZD6phZwC7NprLFLuVoOlwu0k\ng58l38UN525Xla/6emjbD0x94Aehu1asqDpyUJ++zhd4w4UlQfpnC35z0eS7\n1CEb5muUHY90CicWVpmB10I1qftDmi9+yLojTA2+LAEGyHDUzP+seLuRa2rg\n3mj0Uxnl7Nc/CAylKabjRUthtNfZkpbOtXdOxOB5XmNZ7GZ0TRCQTfhdccct\nZFyORgRs3NFsCOIWF5PPwuOnlJQCBEI9FByYx7N+nBe54b/k4C7pZu7fK0CV\n6TQDwE1s9r6918lq8jJDAUugW7SAtln7CsdQlF4qu/A2yWPe4xVkTavMQL4n\nx6BJcb2sQidzHEuDtAwflRUJuOFm/bNH8FYfRQZ9iXJAWmsW7zF6TxmYGXND\nvR6o/KqZUJhHH10oEZMarpsiNNHhZFEy4ZZk+8j4jg6CghL+4Ztw/lBaEwgV\nK86E\r\n=5DSI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB2fMWUIYm7PxGSAX5Qwxm+QsihmX3Zp3Sz4X/Kg4TcHAiBuuc88damLAMJo0o2dgDP2uqM8qNo6jlYVO0znphJs1g=="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.2-2c8ec080.0_1643381781497_0.4477263603269923"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.2-3a74c110.0":{"name":"ipfs-grpc-server","version":"0.8.2-3a74c110.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.1-3a74c110.0","ipfs-grpc-protocol":"^0.5.6-3a74c110.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.1-3a74c110.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.2-3a74c110.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-YuFGwvrCL9BBmX96cO87KWqKv3ILojyJosWdlpTH/40niflIgGRrJGFS4novUfiE3sWK6suf6GPf4yyPbEGAgQ==","shasum":"c41c903250a356a244c4242288ed9dd2b4de22f7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.2-3a74c110.0.tgz","fileCount":54,"unpackedSize":52736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh/VF9CRA9TVsSAnZWagAA9VYP/0C1r8NoYer/cZKToTHh\nAjDEGgeT9JHP5hsw52iUlw+y8I+be3POkKivLw7sle+7n5XWj7x2wRi/g1gO\n8zXoan5mFiV0ZkhWecTURVlyMRn5ANj9tYS8rSbEbKjdwftOhKyCTtybjEGG\nGTWsrR+ffxNenzlSw7I16DwfBJxI4yVnFDn+5Rq7exf3VXILUCkTQ423qV2+\nvLinXUiVxptjgpQJZE/k0Jca/FE1ELaEDmWA9mbA2bh9QC1csm0sH+kvxRZz\ns/b1q4MFHzumDkX+idnRD3Lddllb5rJc1Q6XIrUaxrIOoLUsAK5BIlGJWOVK\nftHqbW5xqQl51O0k2ktirJ5SdBGC+Z0J1Z7riuyjsmclco3gTCbXTQPeDGuw\n0qt1iSRGij6Wf4IHVWWodwyUdT24C+XquTe1xdbfNDBgxD+u0Zf692VKBs70\n6wPw9OOrefyYbzyiEnUNtWJi+fr36wjcA2zq1rwBl4joIXcHlIYvi7iZZyTi\njUurc6XPCiAQ9z8kKL2NorPb+k/533tUeCtwAqetDLZMZLM+I8lpM0AhYv9D\nE2N43J4/J+sN4aML5dDVtWUD0qhTIZGeMuG4Fpd3ah7af4si5kUldkEtYl9P\n1I5PGPuQJoDT0z6uuyWOBpeEHEHUmrRNynovTVMvKQfJ0qjdCtfTgihaxkHh\n+i/r\r\n=QPMF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDvIU4tMfWRp0/0AZxA+VIhn9C+jXk9o4TYltv/hg9inAIgPGgUUiN7T9S6YX8k94evzZLFxLbiR9+5CSUHUvo2zmc="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.2-3a74c110.0_1643991420507_0.7383574417308869"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.2-383dc07d.0":{"name":"ipfs-grpc-server","version":"0.8.2-383dc07d.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.1-383dc07d.0","ipfs-grpc-protocol":"^0.5.6-383dc07d.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.1-383dc07d.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.2-383dc07d.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-RNK/AeCS8Qe7rDtbtQFO92ME6mIVvX2idea5owkJUIw4QhbjzM3jdUSiaASJmPBCtppbAKsm8fEq70Rr5mdE/g==","shasum":"249311fedc1449a2e5b7cc289dcf2a17ca6ed997","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.2-383dc07d.0.tgz","fileCount":54,"unpackedSize":52736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh/YUTCRA9TVsSAnZWagAA1IgP/29/jAzJwH0AJGnAICpj\nUcW3F7NS3Ez/TLg0tHhxKtPtqRb8DhzyFYcIRvbrZ6ZUet45sXVEMH3xY60+\nFpcUUWsorkv4EabSp8i9Rnd2+7Z/2Z+oB5u91kajq1jM7kP/dtg31dt7llo5\njYs5i0X5z6s15XYV6IdjYqH7QxUrUJmXhnPs9Tia4pRoF+UQzdRsixbjJbRG\n9P8gK2FfJ++hjOQidbY3rFj8tzEiifYEKgxu6XQ/SKWZg4Cp3ib2Wfmke8mo\nQCWREXoaixUtR1p7SQTlFUuQSrKSd3A+HCHi0WrQrzDZpDKedCZ+E9w9wLE5\ntUOTc9KTJNZqaiilm1+GL+tiWuIi/igW9TMxSzodMWw1xIIrkcHDvMtYQ89C\nVn0o/TGWFDHCAekskf65uRADMdE+YcvQRhLb8UYr+rELdnAVBRgua5Ur7UpQ\nHUvC2JZPBy5WnsUcbQKsnPlp0K03vcpoIlSuIkGeKozDBI/eF+pV5z0AJ7VZ\nPIxk6rsqxikFQPLd/TNvU9vrfxLpeV1FWpxsD8YVu4z6RYm38JYiq9V6WyAp\nHZkNZ0HYXzRJmCa6T8bGijTSjyJLXazu631LUENwu2bjf8AZbTTVQkQM3SMn\n+CkJvWPuy16mKT6yLwfioqgrgHh0YpYt/8tS1eSLJISoxqvRECgGRaEYMqMk\n3LdI\r\n=qmOa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDAVpnKQ2w6GqN5QhMSNoWH7SC2F7kpoRGbD5lFZVCEYQIhALSaGJZ72Xu6mvPp+DbxGf7Umctgca98CCVJonZVZ24I"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.2-383dc07d.0_1644004627517_0.033519250557798363"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.2-709831f6.0":{"name":"ipfs-grpc-server","version":"0.8.2-709831f6.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.1-709831f6.0","ipfs-grpc-protocol":"^0.5.6-709831f6.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.1-709831f6.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.2-709831f6.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-F6/umQWp6aZ9fG+qRVpX79gMzJg2xpBJJj5yHSZ1pmdhOigl6gTl8GwXMFI8PuBaZ40YXyY/i9T7KB2rd+m0uA==","shasum":"622c21e659196831e2e94567325b37752ee75d73","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.2-709831f6.0.tgz","fileCount":54,"unpackedSize":52736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh//FJCRA9TVsSAnZWagAA7goQAI824egsUbbzzwvUtn9Q\n+HaNxLVcJvEwIF1PR39cRa6Qkx2uFdW/RtbdOuk0tB+GRVAeGHMqbn3yqvdr\nsvNcubLS7KmHbYI6dBKtQO29Sqs4EzfYZ2ElCES9cMubP9uvA8pCe5kigGe1\ny4yJIYQu8emccCsDVWcbOj8yyT7GGJ5aViDvegpw2BGCbAnm4FvtItO1u+Ta\nvcTgHA3qElaIpkblpJuBLgFugIdfdEa2C8WKdpwlcPKdND6kXQGYVHYUur+Z\n5nFkdauEpSf2r4WliSw/kKSPktV4/Wj9ojjuKY/gEqanxy55Dla+xxLar+xd\nWgFNkHzKmn3Z6MchQpPKM+SZ4gONWhZsJq3GAr29WMTdByrXOIbzIssW9Uvb\nDVcbrwjWFbSvGxUModMy6GYrBgv14cgFBpn1rPGRuhOmxQRLUR+OE9emcxIO\nYIST/e6etJEq8nWPpocOh9rKcaF8zzsd/dmeu3mPy568Sd8fDVpsjLpuYVUX\nX7G8lZ7ETk6MpsBGUnv4bR5T0JHQGpM6hd2CqDn1JTW7pKIErOOG4QKtP8KY\nhots2dWMrwY+luekd6yAT0q28FZ/OsYH9/3JJppzoVAKs2aBMHSce13RqjQf\nJCm86IDYOEv57Sx2JkTgZxfUGlaxijmubhis+Vg71yfoxC+n2M+/0RuyZ2c+\nZBE9\r\n=iBJ2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDGRkbiS5xVzwUCJLf3pS8WU5NQVFs0y6zhWs+6SoY33QIgAv+R2HC7OEKsky3WlEcACeYoSPwDEamYa4QBBULUyZI="}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.2-709831f6.0_1644163401165_0.31769427346620205"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.2":{"name":"ipfs-grpc-server","version":"0.8.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.1","ipfs-grpc-protocol":"^0.5.5","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.1","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.8.2","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-rW7FV7PjpkmOTkPRpHoHrZ4/85MtoSLLaWmaEbJm7KEwqbvnYcHHkMfcAvhbWYP1sz0XJCzttfeRWV8KsSOi+w==","shasum":"535fb0a84d48d4484d0cc29d240a357a4432c533","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.2.tgz","fileCount":55,"unpackedSize":56068,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiAU4LCRA9TVsSAnZWagAAQXgQAIhD38TTFhlan7HI3Rle\nMBECGaaXJwSVFjXsIveXC+P3IrnXbCwHn5xnMSR/z37A2M1tIHsuyy1gpgD/\nUa3pTY+ME7hWJhkv9pObbNasGdNioISc48mSp5cnytlWztCl1Ni6VmaDrzLv\nOjrit94WsT6E/IdlqaUnQvnBaeYbfEiMarwXKetaD7MkkSv5InKo1Ok/+0E+\nUyCoC9vDUuvGxPToTf4WfUarFLPBv3ISJDru2XuGT3ieq5KhGKr2JGqOuBOM\nwhA7B+Wbg12UcT2lkLsf2fj5bnF6JloC3SHlozAP5bpQqdoZSHhfi379KlNh\nTbT2a7f5BILMBf6v60Spa8Cs1Rba/N1KGpIJcjnAJe+6SamJYMn/Bwj5I8yH\n1ylMcEoJOyLhBdDsGvsfnoGxhfgKD28SE5cGWsB0KkTk8zkcL73cnfi7GGlI\nElr2XX775cR+92qZ0rttu20s3A/iJYpFVcH7+dY94MZ3+OdKmmBJhygz+t9A\nxu2MBJt894yPL9Qizs+KQq8WXdP+xZv6rv0qjJ2lyah3dsGPaiFcye7RqZmT\nfYqedMdof4YV46dNgiKe7llKyqr80ZFXO+NLJvRmymqpFWgfNnH3YsTrXDax\nEchGe5k9LZJo2KQRWZ0uVyJHeKIgWAj/0sYHDDyjDgUjcFdcPQiCZnpALk9J\nyuY1\r\n=1QOE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD4jBCQsGqrHQdIEcXqfkH5hBT2yANBbq27CdizJw8VFgIhAIY909Zf8abscCYRDj57W+7Old3HtdOMsx9mZBWCWFCb"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.2_1644252682955_0.48739817433628674"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.3-1082fce9.0":{"name":"ipfs-grpc-server","version":"0.8.3-1082fce9.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.2-1082fce9.0","ipfs-grpc-protocol":"^0.5.6-1082fce9.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.2-1082fce9.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.3-1082fce9.0","_nodeVersion":"16.14.0","_npmVersion":"lerna/4.0.0/node@v16.14.0+x64 (linux)","dist":{"integrity":"sha512-CkHLxKzvrpvn+ZSbBaYd19a5n7lH7Rlid0hu6rzgrZflXq7bvmszYvgIXdQSau8ZJR4rCjShPvkb+oLkUMFFAg==","shasum":"d42fd93b28cf64679556a8a658bbef957e3713dd","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.3-1082fce9.0.tgz","fileCount":54,"unpackedSize":52736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiD8YCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmokag/8CsPEw6CNBq4YYEQMpuJpr89XLRKJA/qZU2jsbTnVfUx//1HR\r\nnD5RInNErQ7A9OaTT4A4uMGg2tC73T0huJc/DlZusoCpu8EbTU9Ykgnm2iFR\r\nT6gTEMdr0uhGn8GwHiZiBbojTZKx35vGLyPO8l212sQ/GT//7O63s6QISu9c\r\nKiH6MUcLiv+g/40rlJORHImTZZCm+5Eh6sxZY+S5tijlfNhBMhpEAEncG6Hy\r\n/l1khMKDXEIcROcvbkKWRY0u4KdQB/n2ozzd1UzSeBPm4BCUqSFC7+UPTcuc\r\nizj21aCJsMQTRpmtE8nCywrNkxHldMFcDQYFPlVZ6ltOEJrtpwosJlZ+5M0j\r\nzezfH9jScKrGvaBKRgR6IUe5bJXny1jX7BnatPTv2C6CZ8oA831psUImdUdc\r\nT+a0Os6ZMfVKPs28am5dz75YWcVDTkv3cPbZna0hhdRN588/IEFu2uuLMJa9\r\nND0nB60v9b8almNBAIVf4+GJBCFSGQ4rWHkVUUPoJOGYFs5wgpmlQF4+OA7T\r\nzGwMKXFLezl3R5l7gNXF2EP02UFgZ3ZWxpDIyqUGV5vXMtBsGTMrDDwNFU+/\r\nZ94RIeg8CB6Z7TCMIZpfN1BdULk6ePawk1v6TjZ/ksEsITUlfnOzhLAI3Pkj\r\ntiFNf6nkPZvi2VUuUJtxdznpZj3x7OzhUQs=\r\n=yU/P\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC4xKRYCczPac4hjRwdE6T9K3X8DMeafDoRi5YgzEvvfgIhAM60HQj9C+tm/s6O4YDfDky7xQ/kMPAepqzRQDcVzGUE"}]},"_npmUser":{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.3-1082fce9.0_1645200898188_0.7703232348067857"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.3-125d42ba.0":{"name":"ipfs-grpc-server","version":"0.8.3-125d42ba.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.2-125d42ba.0","ipfs-grpc-protocol":"^0.5.6-125d42ba.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.2-125d42ba.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.3-125d42ba.0","_nodeVersion":"16.14.0","_npmVersion":"lerna/4.0.0/node@v16.14.0+x64 (linux)","dist":{"integrity":"sha512-x1QIBO2IrWR0NfaBPMJ2PN1icxfZUEKr6wEaIPxKQ1Veb68B3Qv3urSfhPVSYT2hAc4sH/EkKErUL3MyeMFFdg==","shasum":"1f965a3a850ac8f6e274df5cf16355ee707080c6","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.3-125d42ba.0.tgz","fileCount":54,"unpackedSize":52736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiHeuPACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqKQg//Q8Y/ye8XT4S/FKBaVR2XEwPdAFU+8stedJUzXHpmeURULPBe\r\n8uRxJADGsOq34pCY0hjYXBGPG/X3KVs2i/CtePUFHp7hoYFoAmuR3ps6ZWIw\r\nc6TX8n9TRckexkB32tUQvSIyDjaGYY+GvGKfN7yESnBlYqdGM9+csTbjr/2u\r\nxb6al0NRLKSlmkqhHkZh1sa89rc366Dck0H4gaGmgy88T8MAqNWrAnZ6r476\r\njo6gdBI7Wo/+KgXvMeUUnKfOUlO+t61ZJzLILWdCOx9DIfbtGsYyIsC4CGbc\r\nTanwIHY38xyhn/d2QrsCDOlGIA5P6tTCehxD0VGYsoNBSQQCbhBUfeNMk814\r\ntTuTfs2+72+AWMjWeA3l9MJwTAoKmQv1SHupyR83lO1VS842I+KpXO3pQt3z\r\nnv62tnCYXH/kssJfepLjW1TFsMVlibILwIJiMv44ZHGf1Fhd1lnQ2FmSOlGY\r\n7m28lFG3vLvO05ZJxyJhWI14DJtOJMNqrL6ezSMT+caYFtRKCSsXYx/9tI69\r\ng1w4nmbG6CBMZchSdhXHJsqelAUgV7MxDX+Q8DC7b+ENcbKZOpJNrtomJKGr\r\nOp9X5QbXid3r9z9ok5Hzgl6K8W8Or6Dcw3XY+LOjshKy26tLlAPQOcBLn6zD\r\n93CPXllvOk4g98T3n+Qgk+anggZWNYtG88w=\r\n=EA/C\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDbtlbOQjX/8uCBbwca6GYRGDk3qtWbxRHcA3qoqjL6wAiEA9xmKed+k1VT2PyLfaIwTBU5ATInjMS/nYssc2rkvhP4="}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.3-125d42ba.0_1646128014901_0.0578767476701767"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.3-df1bd1bb.0":{"name":"ipfs-grpc-server","version":"0.8.3-df1bd1bb.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.2-df1bd1bb.0","ipfs-grpc-protocol":"^0.5.6-df1bd1bb.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.2-df1bd1bb.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.3-df1bd1bb.0","_nodeVersion":"16.14.0","_npmVersion":"lerna/4.0.0/node@v16.14.0+x64 (linux)","dist":{"integrity":"sha512-vvxUzG5FQ7vqms6CE/FmE9hJ9JTvHDUhrh+lQGoMpnRa/TboTlfpQFtymQC5x1e3FN4N5Qj0Dvi3XqPFPJFz0Q==","shasum":"1d4f74b5db9df03549f88748880110e271a64922","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.3-df1bd1bb.0.tgz","fileCount":54,"unpackedSize":52736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiHf9OACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo87RAAkFEVg1QSr4JytkP+tNHPJ+J7YP4nPDqJwYyKBWlrj3BpmMda\r\nTwm34uZlHpXipFKFS7DHjXrekt6JhauGomGlFBajy1tlPz2+NzP7fwPsnR0w\r\nPIygsH0A2tR4G64JUh5peyZFGnWYfT8hNY7T+LPVqe5SXxYJfC8mOIBC4r7U\r\nldJkOIPaQs34dt7qTo8A69ID0KovlfLv7eLMdvQDVd5NfkH00sK2qmz2Ujo1\r\nBK6KjlHe6bN6HvQNYBQ0OzF1fZ2DPH1rgMQ0qJ3VqRczCvGjJQ2+5c/hJmLD\r\nUajPJWoazATTPRldjYW/bD+WpmlgTqTw+CVJx5UH6ljwg4w98oZkU6zd58Wo\r\nnMqeNpdhrMBrPxoObnk9PAaOgrlAtFKe/3qaomvW5OWOcJehrvqFwWGgwuJg\r\nbeo4sX626CVnkTT2x3M2G4oJ/H62XgrPBBuFuU1ieArxSlvU4x0pKsxmy0Ht\r\nBoAxSw8I1nnvjQcCucUndJV8TYwtLjUJKk/BaZeuP29TGwdtwxIU9zSKPNR8\r\njegSyqcnIVuBJfLXqSZTe1+TvoLwgBlxCtVobACFh9fdZF0olrGyozxfqNmS\r\nEuTMyWZ0lfAUZVfFRZGZrQrLhozW5Rm+gvx9TbWEjcS8pDTl3dKFGyLSjQ0h\r\n5wmnIiLJXu01neEPM1AMGfMRvZhO9V583Fo=\r\n=GegJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCEx3f2cQIIEtdRgQILYoPUSJO3WEmxyiMvaK5Jp8qFjQIhALMSE9MSxOzZBDE17aUGsxRNQpjm3u4CH2fVSvol7sM9"}]},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.3-df1bd1bb.0_1646133070525_0.42455332326248785"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.3":{"name":"ipfs-grpc-server","version":"0.8.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.2","ipfs-grpc-protocol":"^0.5.5","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.2","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.8.3","_nodeVersion":"16.14.2","_npmVersion":"lerna/4.0.0/node@v16.14.2+x64 (linux)","dist":{"integrity":"sha512-z9THHrX38bOlPvQV9UIufOeuU7X6/WaMwCugYUDxsA6KV+xxs9DOT+HhdQJTTay9/SU1HzvYKnlGV4EQtP9RQg==","shasum":"3354924b74e9614664ca7448a37f69184b0c787f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.3.tgz","fileCount":54,"unpackedSize":52692,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAiQU8NToJgz6owvaJvcA1cadbqo6MxVbcgff4rb5MLlAiA6jV4hxMahsy373MRnng4QXybQD7G2SxVbbgj0xVt3/w=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiTFvSACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqAPQ/9HZMD9QcWJdryGpZ+J8zM1XdwACSg3CEvGJDO8sZlfYJf4GBb\r\npY/roNMqscRBtaENJFEexLkrVKv7UqrLUQjNIJEvLPSvQMi1Z+BYv+SYsqQy\r\nkhrW6yR3cIxbwCvucOZPVTjISuUsiLHp7TrPrZUkRJz1patQoM8zl+yZ8SAC\r\n/dz+nIt8vPzAnkrQWrhB4/cMhhQGxCZyK6/5RrTOOigw45k36h/JfJdBFflj\r\nyHxIF3ZoDzNNw0+1zPCUuk71+2vVHqsXhjvrAuGISDrd416yPsZufPYTq9xN\r\nX2LdcnIcnTiY5vLrLqQd+yzJcEshEIiwe7h4bUEokvP5UjxvbqNY3cdKthdP\r\n0FZvCC/oiWS6DHlUxu8gMDwEMGgtL1giuxhR6epFkAbThJXdx/+bfHfBZuH2\r\nOSPhJx82nNbSQ7uZgb656bt8uLDDoWMmPaiv6ts33uK1ACBAZJKmWpLG0bG5\r\n0MKgdHc2vreiYwPMri2OCoBBpyfahcG+lIW1XS8ArfPLFcmJCA4Vw0VjWZpn\r\ny/Ii7QfdEwIc7+mbM3+q5AXRAJhadfFTKTdnktyVh1us7kWKahi2taMpOr4l\r\nnFGQolSWMWXanoSsfvENy1tgq413iVEjn/V83v2nBUeRCoO+1SoCwEnnmj2f\r\nJKuOf9mOAPz1XQtneNPCaa/1A3k/4me9biI=\r\n=EIn1\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.3_1649171410783_0.4162122909294801"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.4-e90b8f13.0":{"name":"ipfs-grpc-server","version":"0.8.4-e90b8f13.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.3-e90b8f13.0","ipfs-grpc-protocol":"^0.5.6-e90b8f13.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.3-e90b8f13.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.4-e90b8f13.0","_nodeVersion":"16.14.2","_npmVersion":"lerna/4.0.0/node@v16.14.2+x64 (linux)","dist":{"integrity":"sha512-+Pt8ZXVBWj/5mXXe/VQl9x/OPv94tVxJ7P7vygSF1JgzzkdgV4jwZNyGGORayTqfvvcv4VAOyy+JvwIk8oABKA==","shasum":"c2c147462aa8442c8b2d8fb1f7db7d52d456821c","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.4-e90b8f13.0.tgz","fileCount":54,"unpackedSize":52736,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID5pnTpl+fgca4ZpzNhH+/5TATfTZjzPi2weNfGC0M57AiEAkkr58U69xWZdLi57JFW48dIiBoU+rfFcyLyU3hjjyDs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiTGnZACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrhKxAAlrSLbpmnqdq3c0CGNV3+KVX2F0rq2Zn1y2C0QbXUBYeyS1VJ\r\n3X1VzKbf47EaG7Y0RjbLjKieXXSa9dXGRfufSKE95FQhdZ17mE0qNvXsnFQo\r\n05iZIjQDe4xPMe+8CRa3wq0XqepF4n5UWXqUz5Vdifk/oFM+oPNwGlYTFUFw\r\nmiIlU0pU/WS5x1h8KtgojmcYPkNyolrhqbcXm+C52Q53Y9H9FSfGDG9XnWPN\r\nwPea3YcfXIstgcbtweC8b4u5ZL6UfjGTq/kYOj29ul5SuagXANClFp0HW2Sy\r\nznfvNkwi3hu2JptHL4R/nz+lqJtRIx6TYpu7gKJkkBdiNfAnQdP3XX9FKH3z\r\nEHvwwHjsUoed5CId2UM0mjI52Cq4P4egjYfZ/NEYD5pZYGi1AruQYlIwLpaM\r\np+Ue1lNqiPxAFzhcU4X77MYtBNJFY1rkks0JdLSARwsWaqR7paxypXd0Sa2T\r\n+rXguAe96Z2iSPt4ZHwu2dZ3QpYqa4MU6TjWKtNDA3+NZerSVuF7Qyj9z/8+\r\nnlBbe2nfNCPTZ7yqfgzIfZaDrlmrN7qim7TQloYZbur/+upd7Ud9GlYY5HJf\r\nZaOkMhaN4c3NXRkXlSw6ydfQXjwQAGfSmh2e4hSu4IDHaa5FRmYW5jiju6Xl\r\n7CXBNVW9NAFd0HZRiUu8213nIB+8gkmANbQ=\r\n=fQqq\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.4-e90b8f13.0_1649175001104_0.42054893776788727"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.4-8f7ce23c.0":{"name":"ipfs-grpc-server","version":"0.8.4-8f7ce23c.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.3-8f7ce23c.0","ipfs-grpc-protocol":"^0.5.6-8f7ce23c.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.3-8f7ce23c.0","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.4-8f7ce23c.0","_nodeVersion":"16.14.2","_npmVersion":"lerna/4.0.0/node@v16.14.2+x64 (linux)","dist":{"integrity":"sha512-OZ519l0QWrEviV/YuzO/xCEa0VmFglEBERxZC9Uvcu/x6bWKVyjt+0drjVLAW8dE4n3QaXXyIxN+lvspbZIO5Q==","shasum":"1da90450662ebfe8092801d62402e7beb05422ba","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.4-8f7ce23c.0.tgz","fileCount":54,"unpackedSize":52736,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC46WHkfB3nokxSeQgvuYb8ZhvuHrNEnH3JkIhOZqsDgQIgQ9jj+MSVgJ4wlF9HTOHbWg23ei5zj4HIUJbS/BUotJQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiX/8sACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmobChAAiVJJNScc6untOMsCZil2PrmLsySnbKgcPTyOIX9Zo8OxOa6K\r\nVw0zPhLjhSUsaOG/gBUxf+aGJo/F0pUoVfhzZvkVwWv9IGBWIQhdrYtDful2\r\ns0gwuHvZ9fybPpsMFG8PZ2V5klP2lgPRKKHXcA6huNE6xHcmQKc2ohv3CNQY\r\n7/8vPD/pYCGMM4jVQd5iOOYsTDsiY2rRORY4ryEKirNhev7/87YYMtLsxrqo\r\nUdLIHDDriLWZTlPQ7P0yELmpMDzXdO+sKUq/WqqarRV1q7VTdu1u8aUorPGd\r\nDdOe15O+Nwv3a2ZlG1L5RNE4zSr9rFYbocmJznf8zXZPv/XBr5qTngIISk5x\r\nEzIUJ7eobuDyBsrn+jlKhN6sEYAwx4Mqz0c036a+7qGzr8fK2EQ41aAut4Wu\r\nRwUBZU4OcEtRiut72Yp2vNM3a25u9b0M0Qf6WbheNB7dRBasDRH9MUEtfzOk\r\nDzbWNXlk5F4uKLdqkGCwZ5Vc2j0zj0thLzj09rVhUDZo6sOhiDZT6n5AHY1K\r\nm7VFFTAPS8N7/svSgjVCoy6Vy3w8VjctuL0XcXymCsxgmi7gYTGlluL6eZbF\r\nz15bUdp5aaUYwZnSG3NrRK6HdtoAYucyrbt/wMhve+/MeHXAjEqcVBm4fAdm\r\n5Ff1Zw5U2a2u/zQzMszyatPZvDc+LXnFbho=\r\n=PauX\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.4-8f7ce23c.0_1650458412087_0.8723806866959118"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.4":{"name":"ipfs-grpc-server","version":"0.8.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","main":"./cjs/src/index.js","types":"types/src/index.d.ts","exports":{".":{"browser":"./esm/src/index.js","require":"./cjs/src/index.js","import":"./esm/src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"publishConfig":{"directory":"dist"},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir ts -p check && aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"rimraf ./dist","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i rimraf -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","change-case":"^4.1.1","coercer":"^1.1.2","debug":"^4.1.1","ipfs-core-types":"^0.10.3","ipfs-grpc-protocol":"^0.5.5","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^1.1.0","it-pushable":"^1.4.2","multiaddr":"^10.0.0","nanoid":"^3.1.23","protobufjs":"^6.10.2","ws":"^7.3.1"},"devDependencies":{"@types/ws":"^7.4.0","aegir":"^36.0.1","ipfs-core":"^0.14.3","it-all":"^1.0.4","it-drain":"^1.0.3","rimraf":"^3.0.2","sinon":"^12.0.01","uint8arrays":"^3.0.0"},"browser":{".":"./cjs/src/index.js"},"_id":"ipfs-grpc-server@0.8.4","_nodeVersion":"16.14.2","_npmVersion":"lerna/4.0.0/node@v16.14.2+x64 (linux)","dist":{"integrity":"sha512-0Ra7kOMAsl+4OmWyZ/0st/hLYWzT+SCIFJEPcktUONvUy/mRhbv5/rdEg+l68v/ryY8qd4FhsovhVqyAaICiRg==","shasum":"03e64c35a032edb999bf6c83cd0020249c730a0d","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.4.tgz","fileCount":54,"unpackedSize":52692,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHbQ6rp3JWyFyKGGtHSJToaK7VnLIkesLBxpwfFy/uXEAiAWEiAKH3Aa2ggP6mamJvl6IijlNyF8YlIbGWx082r0jg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiZ5jqACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo4kw/9Eayys0AybPWa5BuuGsQ+1Ye8RrfZSUNJHTe0Vq4VneYWa1ZV\r\n/en2hSV0A5ED3/BiMbW92zuMLKJo6KVBB7pcnXgtlgnBc8XYeiabVazXAyQG\r\n/0gX79wIKBc+Q3+bf0zy5++l4TAAfHuA6AhJs2AcQPzHkZHvclGKeIFflF5Z\r\nD8jumMZjQ2QwSHy5hrBza0E4WQthGkwI5i6yrhIaBLNWKzApBqibhvV6YvtT\r\nElk9DIy1aLM2V+TTik5gh09IXN0Va9ot412CYL5d+9NZL2ggnDm6DTFQw3UP\r\nJvmnXEl+PT/keAmZS55XkvmAgUVbx8qTHCi/WGwCN10FlZhdA05FVZL/0gjb\r\naMTAd7oaFdKpNmAdupv4RupOR+K9Makq2LVVET3ePvUv7b05JijtLhKBZS0k\r\nkD72ALUd0ZQE4rYxBX+WAWY5BCiC3gWpRbgTE1+Xre9yXf2TJvSrXxpoZ31J\r\njABGaEPdI9aMqi2M9La4uUgBvEPjpmKAyix885kX2nHcgW/6VhRa1oDBdcpZ\r\nWIUqUYsEIWUpsk1qu+P4GxozYMuqkCpnrix1R48vFWKuiP4OwxPgyR93lc35\r\n9F8TM25kWAWlrXDDEstCgzPsQI1UNtRRhmEGTVCDPhNmgWXBn+O4kH0kKykW\r\n1y5ROS04hYHWFqFTEb3BunPaDStQuVUWHS4=\r\n=mRbK\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.4_1650956522786_0.3072152795948271"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.5-7165bf71.0":{"name":"ipfs-grpc-server","version":"0.8.5-7165bf71.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.10.4-7165bf71.0","ipfs-grpc-protocol":"^0.5.6-7165bf71.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.14.4-7165bf71.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^13.0.1"},"gitHead":"0ef2fedb9b9cbed1b4855c48b5f03d343ceb573b","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.5-7165bf71.0","_nodeVersion":"16.15.0","_npmVersion":"lerna/4.0.0/node@v16.15.0+x64 (linux)","dist":{"integrity":"sha512-UvSQNiywvdzWAH4vhYk0twY2H6hgLh0gCnLZa/O+Dd1+UmIaVhfXVZOVex3h1K4upFWcB6YcaREeFaOdvomeHQ==","shasum":"56823d2fc81142795312fea8a27dfdbea01011a8","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.5-7165bf71.0.tgz","fileCount":41,"unpackedSize":41915,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFGTKu2X7n5w+kQZ8NXBLd5a22XnxQNVdnMGzK1NReXoAiEA3OpWOX966+jg4d0pTgXrCNBjWw2sRadY0HuDLsYz5/k="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJigq8ZACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmoujw/+LgSH4H2tp0RTflEfUmcs3G++G1L5V/NpeDWGOowv/Qwx+aUG\r\nxL9OucP4t7O48li/Fl7wMxl+j1Qbwp+ko0T4pKZJIPGKIB9/oCl6nrexJy3R\r\nH6DonUNPukJV86zj9EUnteuR5YI7Tp16FPErrMTMn2uD6WERIEVqj42Y8kJO\r\nJ126nVVWgDud7la4cSd5Bdq2ukVpX4J66C2uLu0VsRB8b4XNAp63aG6tvJWe\r\nOCVuovWKG74lo/jni+5L+VefReZZDwTMvreKwuGXOXtVIueidfTHjxIoqODV\r\n7XbfgiDwZnC8gvFTmVMdVUCOfD+6uPPKQdSbpxQyTbPmJtzgp/ZxsGvpHKnN\r\nsxfIv4UGPkUZ5rSrPQm9NZ2UxdDcXeWmAE0xu9KaGvYwVou2sTPj/qIpShKS\r\n5nHEbhnoW5gxF6IfxpFHB8xtQJ0iK0qLza2Q398pxXd5VOP520L8Vfx8I/Eg\r\nLfTvlGkNFyqFCTpSPThyULifFf64zb1bx8jY0kwb+f+3OtHh/BzHyxealV1w\r\nfYwP1Dvbfp2kgcBrRIXn7oIg3wuJeOR2Jzp2OSxuhIQ7yVpK5P5XZKJnpwX4\r\nu71zN6hvjJJpWQO1Poko8MH4iHRr6LONmZ+qog9pre/d4fPCeVGzD5eAGD8H\r\nJEFunWU9Md6uYxlXCWTcfUhdnhqeajmn55A=\r\n=9O6u\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.5-7165bf71.0_1652731673111_0.15205446049115867"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.5-4e93dd5d.0":{"name":"ipfs-grpc-server","version":"0.8.5-4e93dd5d.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.10.4-4e93dd5d.0","ipfs-grpc-protocol":"^0.5.6-4e93dd5d.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.14.4-4e93dd5d.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^13.0.1"},"gitHead":"102f592858ec8237081913452cf185a3e44d2596","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.5-4e93dd5d.0","_nodeVersion":"16.15.0","_npmVersion":"lerna/4.0.0/node@v16.15.0+x64 (linux)","dist":{"integrity":"sha512-z4szRkzRgKKKBHoyAWm/sUGVNFgeVJiYrfS/KDSK/xUC1oL8OgR6UwQGR88OW16ftKWFNArcN6SH4KCbfWoTWA==","shasum":"6d567f7081b771f670f93a7bc132b10f0a89be98","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.5-4e93dd5d.0.tgz","fileCount":41,"unpackedSize":41915,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEBR72KeL3wfq4rTlMDjtM5bL3Yc2Rd4ebmo3aNRDc8BAiBEmFSywiQasMLyQrg+nYex5+a99CnR0dDe2wZHxCSQjw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJikNVrACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpLqw/+OV85k2K036DhuWsR0Q2QMhCcrKSVFBr3QeipzbYvYyorVLNY\r\nSPY3TebonLbj+GAQe6nhOTC87t2Z4rCqKdQLZCPH/eIWmSAIM0kq/bup1DFU\r\nTa0omuT5fxrTjjqeDoQ0UG90b7GdM3QokO67UBwFkuN0IDUxgBxI5ij/BoKI\r\n9LgUPVnxg7piKUvAI2RIXmaI5xy35PtQSlHsoBuYtweAeL03yrk1DjRv4FBi\r\nb4017DlG5wUnt6G/m1nUZQBYBeZUVD3U9jTsHs4vAYe0O0sITJtDpPwv/7A8\r\nrzrO1YJX75oaG0vU4yQV9I03haE4GDo2Uit1u2YNGKs/2Unxq0HgZ4FewMfV\r\nhnM9wr4CM4y3Ph7kWK6gqCcOPsuT4P68AsDVBwNRWU9qbWLiQpr8FI13f5rY\r\nPeFmpqbjT/M6jlOleCcZM5NGi/qzyr5ykaWkuxtVA/o4PAtciD52MMJK814L\r\nLmUSb5NAGM4wTdPmcRtjA4E6ch660D1oN+sFq6hyE1eYLDC8pfkcaWZ3HZG9\r\nnba8KmHzHrsbnIccgeqJuOrvH77UH09mE767XbkgyCP82KuCccFGkyBoNPJ+\r\n2v6XVuI3yeF4IMLt5PrFqrLeFRjnVTbIxihQJe2lcusvvXwq+K81dNfDEQrI\r\nHzxVhDAhuDCQyH2c0or1pXn52kKZm+2o0Xc=\r\n=nejL\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.5-4e93dd5d.0_1653658987314_0.6540128601357682"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.8.5-919b27a8.0":{"name":"ipfs-grpc-server","version":"0.8.5-919b27a8.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.10.4-919b27a8.0","ipfs-grpc-protocol":"^0.5.6-919b27a8.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.14.4-919b27a8.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^13.0.1"},"gitHead":"b3b172fe34f542a72746b3af9351bcaf25bedda7","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.8.5-919b27a8.0","_nodeVersion":"16.15.0","_npmVersion":"lerna/4.0.0/node@v16.15.0+x64 (linux)","dist":{"integrity":"sha512-zq1fq85Py+xYzn5aKG7DyexSCWuOAgck4LMjM8CCnLybKlVrhtjcOCSbfNLxkWNtIHziAf2neqUZ23MRL13S7Q==","shasum":"89d368713d60780f70a40816f9f489f4c6f49df2","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.8.5-919b27a8.0.tgz","fileCount":41,"unpackedSize":41921,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCm/dRcuvIltqByOVcM1ZRMamBu36a8ovo8zRhmSTL7HwIgfTAIc8+DLm+AhquD9tmBq2wkB8hBwwMRWtIrOnl4+kE="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJikPnaACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrbkA/+IFDm5Kl8m+39mloVv/ToX9HX6Xi34w3vYFpmzuZSz9Gyoe1C\r\n/PIyEVfDpCxVfidB377/P/v4Kf3RP8oDsBXk+tkF1hEbuyKyeb1sKU4PBBqX\r\nbQC8A4fAUg3cQadlsw/f2bKUa0qErH5KUmbu2QrOUxWK9OxgJCksXl/JLZBW\r\nPyuU8jXi0/yGs5UYqDwIWyzwjHQf4y+zrQvTyZifLVLG0B8UxWjGy/0Fp+Dk\r\nZjLElSsTYiHP1apfddQrDTqCXBg51n40uRRmVXr/3iNvUbKHQH8vzE+I+k5O\r\nnUvmByShe8dvuVnfijWCO2bJk5dlhZ8Tjhs+9e6pVyROCTawZRUF1icin9EP\r\nXtu8gTe+/OzKxCNbegKUnkAuUVLDi3e5z9Z8vD0AxereeaNjoYTQo+K/uUlE\r\n14864kMjUZ+wiUjNy50spwDqB2M8vzSpNOZ5d0cSB+x6s3GJMa5AbGPzoq85\r\nMmXNFGmz8YSttrz5edOINI1GaZwS4liYMhJaeHE4lIVIuOY2QBN0ls73YON1\r\n+0CBK951b61l5qitNE4LAzXgaIELl9I+eXIYdOS0vDEbXge7JsSOfG0RxT3m\r\nurKbpQ7jzzX0DRHiRpy0gSPOqzPULEFcjzGO0FxLG1BFJqVOp1GdYuD55Yr1\r\npH3mV6mxYffoXFjNPd2GfwLDmrCHSUIewRI=\r\n=3rVs\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.8.5-919b27a8.0_1653668314452_0.3807106463812122"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.0":{"name":"ipfs-grpc-server","version":"0.9.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.0","ipfs-grpc-protocol":"^0.6.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^13.0.1"},"gitHead":"38e78cc875309ba6316706b63865e399dbcd18c0","_id":"ipfs-grpc-server@0.9.0","_nodeVersion":"16.15.0","_npmVersion":"lerna/4.0.0/node@v16.15.0+x64 (linux)","dist":{"integrity":"sha512-iJZHfyIFF3n/Dx30isFA5KvEQjpc8HJ1SmQI6si/Vpq0JB5Oy3T/dAbSdby6OMarhU4NGYLctDaCaAbcmEUXJQ==","shasum":"4a50df407bc69d6ee03db0b7bdfa0008f78e0976","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.0.tgz","fileCount":41,"unpackedSize":41877,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBzQcjc/juFEUUmxKcInIcdXa1brVA6uEnonWOFPVAaDAiBISmnY3Xgr9iFgVmxv1H81y/jJPDV9JKO6r69QsxnCJg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJilRg/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmohHQ//f+xNnF4twOvzPo32PqUndsgJoyA6gUpLqelHMq7Bs/gsQ5Nj\r\n9y+htD/mfdaI3V1fQ+WNiM3bmJ6RbEHyOG6Vx5xWWmYNiy0Hy0sl1UgnZ1/p\r\n5Ym1Z2tB144magyxIWCrE0aDXxrbiTDpJPLOXvfwJJQ5WnIEPmzbCRjV4XE1\r\nsKFBU270n3r9tkdoLPtalNBUkTcc9hvVBXqODCnOwQeRk2EF6czfiuocngJR\r\nqcJepbIkcHNrvjATgOUb31S7NGl/NGKX1/LON4ZlZPe1r02EDzfjD9LAfXvV\r\nZkOiQis5mRcd5rDanDldxB7t/YO//wJRFNLgKKIVVoMswQcsSqnBVs+Q3ePw\r\nnu2AxUpmkBbnBpmvT5yR5uKJkGuukGYUskQP6i3sztKAg+AkuXYfJrV1RVBt\r\nUebk9mKiTWAn5rH7SgO0cnb8hwKDbVLu2PwV9za4JY1A7FT+zk8afrnxA4ES\r\nz4ZndlvfGx387GMhs7TCGhZzeJs3dtIGIx65cG0R4O6nEkbaLj19LMv3XscN\r\nWSrapKBvSXZUlvOpgFkrQ2NO58Kmqw/6T9YLB3U25wWs93TIpJC/zFOrPDLb\r\nMKWxpaUwbqaCNGYWAFMxzgw0osrTA2qPjwhGDc3LeCTuDSCcKDGeLtAiS41+\r\nE4Op0xGjuz6gi/6Zmlk0h/f9o1UrKCEwEGg=\r\n=1jud\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.0_1653938239370_0.28141288252337815"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.1-ddfb899f.0":{"name":"ipfs-grpc-server","version":"0.9.1-ddfb899f.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.1-ddfb899f.0","ipfs-grpc-protocol":"^0.6.1-ddfb899f.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.1-ddfb899f.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^13.0.1"},"gitHead":"87fbbf38470547cf82ced4c9fd2679df026170bd","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.1-ddfb899f.0","_nodeVersion":"16.15.0","_npmVersion":"lerna/4.0.0/node@v16.15.0+x64 (linux)","dist":{"integrity":"sha512-hDjxYHZ9Ta4h4CSUBZt0ZFbfbIR872ii+U5mwmL1ipccLKpbt5HIJ/3ljZ7T+ILxJSV93JEPnoSzZimGHK7WGQ==","shasum":"63357c71f4c379d5a795d147fdd4d6a52ba79706","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.1-ddfb899f.0.tgz","fileCount":41,"unpackedSize":41921,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBunphwm/V9ATzq2tAiyFogZ3g5RpXKY89A1fit1IhVzAiEAtOorMFTsB/wYevsqxnBZVougoPF4cScR2k7OcQrCZx8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJilSGJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoElQ/+OLUH1paTWQYK5DzKMsX2sn/pNJT2C/PbZDpkFv1c+FXuu9EY\r\nt1zqCcUVAiwRGX3aeqmiKWbEYqxtUPBZFJCyMgS1axG989Ou2m8TYhdbWqtC\r\nsbV+T7RLbt+npXuSXxHAgL1gNLZ9Zh4pW04Vab+34Ph1R9eZBYaqcpyhDz96\r\nH6GgismreDSTK5BfxNAMzWs/idDV1HUl8uMTM6R0lHl9R7Cdek6BnoOURIal\r\n6fINJlZ7RJSmGmJ0KaD8EzR39m4dVydE1A6MgmQdDOEoLSq+Tvu1PYhppGIu\r\nXRC5EmSDBsbgjpvIIBxnvQLPBIAe75pI3Ud3Z33elizt83gSJejblGkvWGWd\r\nwvaelwc0BzMecZ+qC5Z4LBvuHgDOTMWq9t1lV5KskwlRBfu14dFqWkR/KFne\r\nBzza13xi43XxHNEFPdeO1kWsg5fgUZAuflp/F7hJ/EtPlCBqPWhzXibX/+nT\r\n7rHzqQvI/cA7GWjAa6H8npmBCR7mO9YaAaymOtwBS6f9ryFqww+kzIfuhsMz\r\nZUW7/TEdSrEOltl9jTxAXB+dxa/FtNR9cduJ8WhqLPPD/P2l2kVFupF0jNhQ\r\nvA9SJr5AWCRIhFh0FrorsjqmmrlN2FRgkZKiHLAhZzZ6ea4vJX5ncodgNow3\r\nXf4DGKj/N9qGzvRPrhV52DDmHBkTqsSBgdk=\r\n=3LHR\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.1-ddfb899f.0_1653940617189_0.9564377198627136"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.1-764b4adc.0":{"name":"ipfs-grpc-server","version":"0.9.1-764b4adc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.1-764b4adc.0","ipfs-grpc-protocol":"^0.6.1-764b4adc.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.1-764b4adc.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^13.0.1"},"gitHead":"e174046b9ececfd2fb7fffcd8f6ad6211adc7499","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.1-764b4adc.0","_nodeVersion":"16.15.0","_npmVersion":"lerna/4.0.0/node@v16.15.0+x64 (linux)","dist":{"integrity":"sha512-ZSChXpQnuQwztUJtNzSVHhHz8YGrKlVEkdaKUP/EXgRciyC6xzUvIem1u6jLgKT/kFOnXT6FZf8AZv4fapMWDQ==","shasum":"15e842caece03539c593195a18e72ab95e281514","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.1-764b4adc.0.tgz","fileCount":41,"unpackedSize":41921,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHYMWJKCWHZlfuN/VhnVs7jTwr85nX+bgPmz2UtSXPhMAiEA3npeOlO+tBKAOHwO9oiVFKZh2rvtykA8WEKlojNDXxQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJil3cMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp+xQ//VtOeyK0w8DeV4eZcq3hul9gl+oSmzi2hp3CNGH6Be3YSGU1F\r\nY7WAxM2lm6K38AwKLGusiKTuZ+6bivwWfo/SFMyEPR3Kmpvv0qXYcINOYPzj\r\nPoXr1z5aeJHfHbhgUAQghBzEziC1I01c+uBiBcOt3/Ezp2tkSleHGquKEjWv\r\nLC3PeZvc5gqWVoKMfl6HLv4N5mFMwkT/khZYfpiDT/KOWlko2pAbmbBoZlfD\r\nLEMtxHfrcFvL9cQoZ1Knp5K5yrtMMJjeeS2lckhq6MvsMirWif4LwjssU0us\r\naBY7BE0bw/oCF/dHn5jy4NiSocRXGEW9K75XKD4LlcZz8nJQc7RvnF1Y7EwW\r\ncB3Eq5Y2Sq2qd0qX09qHZ+/Rc8BAxcw1LMSoF5l/3jP9/ZXtJm+xLBzXZ0e3\r\nhP8eyu9Url9HgwBxWTrCPtkRwg+F4JJUrs1U4wB9VUQKn95GYIlP3iOxrfIE\r\nfJakLXT8Bj0nzFsXtl6DgPFHZQNeTDRxuIbrtrKV5gKefOfUo2uTwO8LHIpl\r\nxfsPJYa5rjKcrxS7XLtav5zRRrIeMZpiqxcmij34nIZ+L0A9aW29C4oBd2Xh\r\nWbtKZCeetLdfhtTuh8iXfXfreE7wX/eIgZBJqneIqvaAS9l67XqiadthfaPn\r\nQpA1fAdKgpN74GgLUkjsM5VqIFCcH0lItDc=\r\n=UJnP\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.1-764b4adc.0_1654093580504_0.4852429575389572"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.1-be025c89.0":{"name":"ipfs-grpc-server","version":"0.9.1-be025c89.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.1-be025c89.0","ipfs-grpc-protocol":"^0.6.1-be025c89.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.1-be025c89.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^13.0.1"},"gitHead":"624dbe983b6f235125107b73ccce5ca3e45cbe7d","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.1-be025c89.0","_nodeVersion":"16.15.0","_npmVersion":"lerna/4.0.0/node@v16.15.0+x64 (linux)","dist":{"integrity":"sha512-FN0lQdbepAZJFKx7FalLXbNLM5xOf7bbH91jl+tAKfooMfmwA5Ldn7HRUY6JBYNKORHc/rC1pW/282pglBCVJw==","shasum":"74ec84ae0772ed5d7c1892a467834d3bd9396796","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.1-be025c89.0.tgz","fileCount":41,"unpackedSize":41921,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICjyTdE/IZa6qLGgIhWItiwjkQ1oMGYlni25gqMaQYqIAiEAsifH90a2QMxXBYtMvWiOxVbn+aHqKfFnzcTektdBuaE="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJil3hEACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmobOQ//T1YOuFDB32TxFjdNx4WuMZYN3faA5pqLT12jXqlUyo1j7kF3\r\nDDxgvcUIw+Vymfde75KWRBJ+M689fwO+8wpLpqMtLzm4u6bmFxxp787Lyu06\r\nNP+NRDUXe+Tqjk44C3ATl6g2Wd4JxaxNRlhaQvxn0rHNtVGs1C1vgeUNkqOK\r\nShCXliTVtG0PP55/SZt7qcwyF+LiWFf94deXKoSk8YzO1zVLT9R6CCxCwc0o\r\n1TuNBId0KElc0hnJ6mSH+viDOasdjDbmFI8MGcC24TyaXtpLStepF20PSNtq\r\nDMdxlDEfBL/Cpx93PLwgiqpavWNVeT5c7WEG9yC/9WP3JntIQfDLooZG89Sr\r\ny6gsqqAwPW/dD09U7USbBh2aBLYFai5nLCIxEBXZlcZ9d00M1Bpkm5lWwbSL\r\nbxVAccI8Nx8fjfTnlxHceBJNpETdgRZo9zNXnij6GrIUWmXX4P9iCxgfnykY\r\n18+Ewiou4T4n42CaYJu3OCwoM/yEcHaQ1uJu+yHqvY/iJWGYAWRv6dGJNs8+\r\n6tmATyEO7ijlVIDb9Bz3xdnRVF9KWOuKx8AmBPdIPVuVuAHPjkG17YD9ywVO\r\no9i1nB+rsACiOk7x45iXuJuoVhIiJ3/4h3DGNt1B0bbXJ+Tt1mKXswfXc85N\r\nwP/Fzg5vZES2eessal5Y1KcqFxOl8JWJkDE=\r\n=e0H+\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.1-be025c89.0_1654093892073_0.16968491827570853"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.1-87e00a69.0":{"name":"ipfs-grpc-server","version":"0.9.1-87e00a69.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.1-87e00a69.0","ipfs-grpc-protocol":"^0.6.1-87e00a69.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.1-87e00a69.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"4aa63330e4f3184df8f4d39cd0880c0ac903e795","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.1-87e00a69.0","_nodeVersion":"16.15.0","_npmVersion":"lerna/4.0.0/node@v16.15.0+x64 (linux)","dist":{"integrity":"sha512-kbE1Zf6qgb2REVXq23j8lMu29/0lLMlKQJ6B/7XRQQiOQrozFsK69/U2ZbqM4RUXEzCBCF1qBfWOgRPlpSBhmg==","shasum":"8a2bd353e8ecbb0c8857d0a48e8d06bbe1609b74","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.1-87e00a69.0.tgz","fileCount":41,"unpackedSize":41921,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEvi7EXsdHCEFF/10mn0vodNVvG7+VcmmkPDIrsooWWwAiEA4n3Tn9lkzmBJRZZbjiU0DHgs9ftScUpvu+WUw4JpoRw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJil3leACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpB/hAAnZry3JQHedWNMKRjkL0Zd+aYpSj65QnGcD9YXsAleLNLjdfD\r\nzVog9TnaULnHcI4hPF7cykT0p4JEziaD3Bxw5SpQmiCoXSZHcdoJ8/X87ixI\r\nalheevoMcsM7oyWVd5Ba5pgNYP1TvIaYr7/jrt4Ctq+GPN/17X99RIt6ZUxi\r\niAUn3h3lLoIs8XFhTAp5lHpnz5qk6vdZCYfMaPOaVf4i3Qz41kriWKwIvNDb\r\nMzflmOwgWz9ApyirBL3ZbGSRmk+bNH7W8V8XGdGsGykRzfClAwU3LOtpRiOZ\r\nKOWK+Hykaghq7ZtKUBUocbuD+mGu5b1zxSVaYv+5JKhBxnaC77Qh50mFOwq4\r\njpnFdRlIvJlbnPScQlI4VU/6pz76AOMC4sWO8zGsLWvRN+DN5pwkqsCK5RfJ\r\no8tmgfOcYnPAMMw+GMQbMQYqKL7b9k/rBqFNMPsmYoKPSG+PPWkZREXk4u09\r\nwRywY13EvCBfo5jIo1jxVrDOP6FvR0Md8vd/1tdpuyiZXgXq3cPJHI4V/YAx\r\nCBkY4/S/TiwuEYG/gZZByhknDRUWCUpPSmQESHGFEWr+PegVbYsjRUqOUlSx\r\nbwplTPAZA9b2vS3HMdKaijsnbYll42axikHyy15qhJ337QayIlo/earG1eTZ\r\nJBMJuMnESVAv22swe4OCuWTLNGxFLC+ojr0=\r\n=P98z\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.1-87e00a69.0_1654094174001_0.9547426802945351"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.1":{"name":"ipfs-grpc-server","version":"0.9.1","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.0","ipfs-grpc-protocol":"^0.6.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.1","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"548cfb215e8afa8dca64d3c38fa13feecbe577e2","_id":"ipfs-grpc-server@0.9.1","_nodeVersion":"16.15.0","_npmVersion":"lerna/4.0.0/node@v16.15.0+x64 (linux)","dist":{"integrity":"sha512-d91YNb2PpCMCwbA8VzAvD+8Jqr5CXfmQS6Qrg2Bu2E/VxL7Pgyxr819DU6ZvlCIO+AOEdqYKTbnhYeHaKCqNVQ==","shasum":"2c5c920fab9731cee921653231a588ac2afccb81","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.1.tgz","fileCount":41,"unpackedSize":41877,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCBn9zn+S0DrfWB4qqgFZZFgyyNtyl6uwg8wyxF2bsfHwIgbtNSJHpA4YGp3r1YqR5flfR80MlnoaYyy9P3BVgSFmU="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJil4LJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrrUBAAnE8IHhTJAsN9rPLTy/b4OfeO/Lhedf6OC4bWJzFgiwiebJZR\r\npb05m4hx5N7mdd8Yuf0R2VmtJ3sHwv19uAggcDNQjf2gEMtFsjDc/3j4BkkE\r\nem4MuVURes0d6+F+nMnbMGNYnK1SNk7pLmfs0yKL1uXV44Wqh7QrkP+87Yky\r\noye7KT9ymaYlzGOfFcxMPpxh4mfFnEjGH95eBgNhspahAc7UhLcWCceJWxxz\r\n+kul6RWO56AKmekCEnDCItqVvrKYBt/aZH1fhhAEovN4OnHIUfxd5rP+5UaP\r\nZkoScIq2IeMfZppDbv9mi47mv6KgsaPCxgPcz5E3ckHGJUN3jgAI1hBHQbW+\r\niBSWRRijyMBPW5dahevYdwRfC5BVm3CvM9Cooabwxb2hc/A5EBmZlzdGnV6t\r\nAXtEljeZvOjnXyJDDcsxSuowOKjBWhAGPWEhHRNuL/5WOHS+BdoqYsQWbH2T\r\nGtTAR6fY1oVwe4XvfwUJ2m/6mPCnWoduwJWSr5gO05sjETHHGTXlQs2voqIL\r\nIMUwDTLUZhtBGD97N27Zi/PzHeraxthHd2roLX8dD/mOGWSV27ByuTDv5CG4\r\nPtKJP+QRVeqnmGvl1fawUNQZYZ7Sz6O1IdZ2ZwsTgOqWGxrNa3PGRRwkMXBJ\r\n4W3s4m5el1788CREtfN0GtF0MqrIlc/H/qE=\r\n=NB6d\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.1_1654096584995_0.1054312447484973"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.2-70e142ac.0":{"name":"ipfs-grpc-server","version":"0.9.2-70e142ac.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.1-70e142ac.0","ipfs-grpc-protocol":"^0.6.1-70e142ac.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.2-70e142ac.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"1a6e6bef85bf35b9328b61ce15d312f1961f5fef","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.2-70e142ac.0","_nodeVersion":"16.15.1","_npmVersion":"lerna/4.0.0/node@v16.15.1+x64 (linux)","dist":{"integrity":"sha512-RaBApv3Zm8EloBYMg8nBvdhtDu9fUs9u5Hdf8j24gT91wW4uFqfk4taOod2wh1Dn3cOmZ3h0ZCX+WNx39i8Y1A==","shasum":"a48d8cacfa4ff4ed0aa2118741e7b8dd11ba6fa6","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.2-70e142ac.0.tgz","fileCount":41,"unpackedSize":41921,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHiQLA9s1ufysUtXoO/uR2LNkuULfie8O/EkANgb+qmiAiEAiKv9RrpRWSTdgqMkXBu7UJZcFiIiTYJ/2TbufU7awVY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJip18gACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqRCg/9GruH665BLqYVOLU0nkMqcyKsB7po+Cz/mMEvmsjIOU7WJ6Oa\r\n3aV3YZ4ITM86Wgffsi77TGM8r1aOWKBZq2yt8OYtXE1iaZyjPab482qn9UtW\r\n8RFRcN2/beKu4N3Krb+Sd1jK6KcUmwsVKFmKd/xFiTEGiIYh2wx24xMEP7+l\r\n0AyGLa2EjFs98ik2YqkotBeU3HTaNjgglBXYF5fQ1UradDdT0jWJdJ3S7mKD\r\n6LfHSPAzGpAfVX8XC/HLq/ejNsEvSsr8e46Jjd/5I2ypLWMjKU2TUuPJfMmw\r\nWHHQeWFIRM5QOJwCaiKaQVtKTGDQAw3uyVOVYYoWcXp8i+YwubnfjLS9rsuG\r\nTnyKcskJniby6C74QOZqAcBCP1r3TXm8SuuAiRlkd3RyKaT12M7ep9RJ++av\r\n3FoIxRTG85pKz400BSvLd1xoKKVSlIXgXvtYHi9aAJ8RTvCD7imkATh0Igse\r\nHUIq7MO5U0uziOGnTtzJoTSwDtx4+wDP5DOMfvTIaz+uhHJa5zAs1TmrJ8O5\r\niMRuvbtHBaFPpIsZzUHPBjCqM6vW3rRs1MsEqX+X2N1i8+K8/yo45BOFlEQe\r\n+ZWWLz+zkR7OpUybNJWtnL84uFk5raJjXVOCuWooCcsmRm8TZWKfvpKz4TWn\r\np5N6IFAYMkVMuAKYZXPQwWJsk8vdKZ5Aze0=\r\n=//Jh\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.2-70e142ac.0_1655136031766_0.7647699875066933"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.2":{"name":"ipfs-grpc-server","version":"0.9.2","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.0","ipfs-grpc-protocol":"^0.6.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.2","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"0078aad85f92d7bc8e3a22eb9ef8efd257b439b5","_id":"ipfs-grpc-server@0.9.2","_nodeVersion":"16.15.1","_npmVersion":"lerna/4.0.0/node@v16.15.1+x64 (linux)","dist":{"integrity":"sha512-2g46wQdLdLSB+xDC7gXblCogLoSK3LLZ0s40g/bFY90nppLov75Kr/fkbcE0pqxjYunmZgwTxkA/FM23xWJrGQ==","shasum":"704dd76d5da2db5866cc412d7ed2fe7652199c89","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.2.tgz","fileCount":41,"unpackedSize":41877,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGIBvBtb8RlOvfICBbfp3jVvn5qtYKYXqYanaRHKtcRKAiBzfxFIo8O5q4M1nYCMfdQxrU3U5jkYkl5rACSjwFUK8A=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiqCnTACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmprUhAAoSvRVXGlXP7S1YVmCwA1kZiK5tv7v59OTnoZ+ecJepWBtyBT\r\nFrPrhCDY9Q2x2dAOSNDS+VFQMTCOO3lakC4dVkdqSil5J1g4eySPyBFJJ5B1\r\nSr0c2rKN12xCMiGKVjZOUjUAVLdAQLbp9e4OckJcupPlI1vT1ZMVnVHN0+V5\r\nqIedqLHs2BoSuNuJ9HnsORwUEmhc5lW0o1xtSGzYOfQpxLJFBivdm5Wd1ddv\r\n2tiD+FZ0TjQ4M2isu1eRbdgcWocmovlymDZSY1DvKLq9jJpzQhyMu0B/dJTu\r\nra2Ha+9P5wsodkO/1D+miUuQ9ZWodkdqq0rFkNOV8hd45yBlewBUJ4ecewZ/\r\niGfDgysVGL/sV3+B+6rJTzu2lgVcXenQhdn+VK1HDKwg67DOebtixB1rvy6Q\r\n0LV+gyLyGiql1ZwPA5OUgMJtoST1+QPSPobtrPhCV/LVYqIoQZN75UP7bJX8\r\nAk5luSJg6eUzslOAhaTyDViLi0wmta9jAo6Aer1ZsCrJ0/uWv/pa8khjQBgH\r\nGMywCaiwqU+3VceW7/wXj37eUZjAIU8/TLnPDW/zgpJNYmivUNYdDyPS6zZQ\r\nD+V68h10SHEgdb3XJVhhTrlwsRW8r5qWzFs6Gf5WY/rpb7+mtwn5Pc8a84+A\r\nRu6qauvZELTEH1qfpg7sepEYbb1d3clrBH4=\r\n=INVG\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.2_1655187923265_0.4771559686206297"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.3-7be50bd1.0":{"name":"ipfs-grpc-server","version":"0.9.3-7be50bd1.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.1-7be50bd1.0","ipfs-grpc-protocol":"^0.6.1-7be50bd1.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.3-7be50bd1.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"8d1e141b6d72e6dca9162859d36425eab90d8b12","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.3-7be50bd1.0","_nodeVersion":"16.15.1","_npmVersion":"lerna/4.0.0/node@v16.15.1+x64 (linux)","dist":{"integrity":"sha512-Yg1Wbvv4fyCksIWNoIpwlCDfAuFOjAK+4dLY5boSb+02lT5qYij8TeOJJUF1+htGOJKHshEOWgWYk1mKWwc41w==","shasum":"7debd1613562fb0382dfb5996360cbef89f4d093","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.3-7be50bd1.0.tgz","fileCount":41,"unpackedSize":41921,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBPQqLk6z/Jzw52V5vyEcCrswQQWBXdHfKN4gG/5y1C4AiEAp+afbChrHX50v+F1cAvwcJ9LQ3Kf4UrJLUbRd930GEw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJis1XyACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpx+g//epJC+HJUtqg6ZGr0o380LC4GwU28Yyl8Eju2xTju+hmq1Ee5\r\n8uQYJ9wJ3lShh4JY0e+cgvfSZmhkpwvbyUV0OK9LPl/H3+rxAvUNeAyzANn4\r\nH6znJegTzR/wuGKLFz8WngQli5uvUd+0iqODQ7WcMugoedQoITzGp4pFZq+D\r\nJ8xLjbvkVXGKQ78Eg4ZBT4+srwVyAqVwPkNAndHrDTDz0jB+jzeV8Fsw7dqZ\r\nXDmC/8CUQU0DzxEg7c6dqv4gZOduI32VFl8wwNzDuVIg75kBE2HQpJG6X6+/\r\ntIs3oXweS9yhR+NY3b2xUTlqhRXbsioZ6Z/OgAe0+CtF+d1s/SUcrywejTUn\r\nvvlwaM7LCEo+xe25vVU3BuLOFcV1ag/W4IeGb+n0lX2KgA+4T4PnVrHnbXE3\r\nORg6cSkrbslGJacQDgnaXz+ydZLTsmZ/Ufnied7LYHRJMn9D2VwTD0jgAQ8K\r\nahZ0m+sNta/TA3mhFB35aYWK8EMCGR3VgPg+BIRwpLJhowYS6DQ38Tm7/ycV\r\nUmDQ6LSe6hfqJN7VTagDUQ3u0G0cHEmBjh+rVMzcyjR2Eb28pY16PXEgLhQM\r\nqDbZWT1oVa2yQ0YE0GXZyGSdQ8IJYb008FQamfaslFyrZ2UJKvo+0kFBJwo6\r\nJUwedZHT2+XnnAXI4AjF5JJbbOk3Lb8vyCQ=\r\n=+H0m\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.3-7be50bd1.0_1655920114414_0.7841104970802788"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.3":{"name":"ipfs-grpc-server","version":"0.9.3","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.1","ipfs-grpc-protocol":"^0.6.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.3","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"c1cbc810679405d5a5c0fcca0c5c7aaf023b2d22","_id":"ipfs-grpc-server@0.9.3","_nodeVersion":"16.15.1","_npmVersion":"lerna/4.0.0/node@v16.15.1+x64 (linux)","dist":{"integrity":"sha512-X2r0eEtYPqlksj84c5R0PhuJjJ/h90C4u8nBWcyIt3BbccLVnDyDcwq1dBetg/VEAQOQic1fsWDRFsJ7mIF5uw==","shasum":"5b069a3ed131d3926dd30b4fea8f6bca771db080","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.3.tgz","fileCount":41,"unpackedSize":41877,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDWoaBXOUlZO+t6rAxgHSzlhPiiPrdOl0P1FDy6rfL77wIgEq0WpkTzwcZLwtnAeAw9IA/sUPsEBG+jrafAv+w0fow="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJitFaBACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqleg/+JHTej09MIm30EslW9vBAIMmD6JaZ0Q9eHQWVaQ6TI+cIMjGH\r\nIKPL8EcXIFEqPHFEwIKos+4vPzuCfDAvRbKtUVNx4BjgQKYETqDWRDQ9h2zM\r\ntFF+9rZgyf0NeJZBRaVxlrJhtpebyhAXweZyldsMcQ9oyF4XNL1YxWD/090o\r\nM3qNfLld0521zHzNNVt5yM2c6MkrL1vw5k9YDRZsI72eyzNcVh2tImPZu7zk\r\nDCZsxZWpJoNmj6Cec8U/RjwSeASYeVIvaVlWywilnP1FkNpywbOcuQWlOr1L\r\nOPC9CACrFqs0fZAg7u1cjbrc4ZZzXY1R8JIo4glr8i3jWxGrkbEU6cvqHGRZ\r\nrXP4k9N1zhJEnxDPO93qmitsxGoGQ7Ufna9cUZys9lZh8f4BWhvmryfATK5y\r\nJIizCAILPdFRpL3cB0MMPcCuXRXed+ROdWHNnUQoyp7xMj/QlsHUs53LoznT\r\nR4YsQB9RF6DAgVJ356bOwSWbCuw0+zhwTiIOoJFf/oaBRi/PclYOGhhNPopW\r\nIpo5e7C5AChRKiWtxS5VznkUul/9StHyRijlkD0kWF0/zw85y66KaLJk+A4+\r\nllYr0WEy7wBGwiKPttvuq45Vvlajqp1SNROFohD7qwAu3NZttoMElH6FuMK8\r\nemC1PcSJf2a19EYafFo4vB45N9VW2E6mUpY=\r\n=kQmh\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.3_1655985793463_0.14995028826024615"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.4-00bd3dd0.0":{"name":"ipfs-grpc-server","version":"0.9.4-00bd3dd0.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.2-00bd3dd0.0","ipfs-grpc-protocol":"^0.6.1-00bd3dd0.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.4-00bd3dd0.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"5e5669eefa320838c4810adf62356b0039209ed2","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.4-00bd3dd0.0","_nodeVersion":"16.15.1","_npmVersion":"lerna/4.0.0/node@v16.15.1+x64 (linux)","dist":{"integrity":"sha512-YaSAxPJeB/dieZJiSw9xrNSLSS5g+TFbnftuHBHBqN08MXA5py1zzBp22G6yeHXD9fm1MsaFmNmzbomsQh4S0Q==","shasum":"9f6396a06b612c6e1b220b143da02c63aef33b78","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.4-00bd3dd0.0.tgz","fileCount":41,"unpackedSize":41921,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF7I08EKZMcyKf+ONnTeZCwX7YL5vnT5SiA7KzRGurZ4AiEAuaa9o07uO25iFP86MeWOanyQgf7jb2Tjw7U3FT1IrqA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJitYRGACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpkiA/+ISIgITy3urPzLYuVH8tao8bKBqanAni1NBm12aESTNCuAEKb\r\nsbYd5Gp/bzIz7YWz3UsxICK9p1qdfXNP6jQPW6a8Rny9ZwGo8HHb31z0fSvf\r\nyl5ZrwUQb/0qnp3P4GSM1JnfJ2/ry3G2aewyy0A3aOEwbggjx4QxWbpeUjFk\r\nPaHfFzTz0xm2ZLzkE6ea/CpyzgNw+UzaP5uFZKhiEfLVS3MGpMf0dG4fkFgR\r\n5oG1vnrf49PzU44HJUaRyffrRye03B8Hyx+aNL1N08QGwlUv/BI9CR68HpLD\r\nr3/o8HfPVgCzxrOhhwRulaS5GF8xOk1jY/bOUcqpb003kf9B5waqenGQ1Xj+\r\ndrVAIR7UyXv10GjiPyWDb0l4JvZRvylGAQRrHRj2uzGau2VClS89dz7PBaon\r\nFGbTW8n9Yt/6vf3qanyNNyoMtTb52CVTCsGfg76ZNT77rRmBO6gKSqqlNybL\r\nqY0PXYCM6LTvQBH2DiL/WtKzkmWx4zlIm/IpD/MFALDXjyZhnG0Yvb2TX3ha\r\nhltcrp5goaV9jbxdys+4TAOWrJcnbS3fynHXfH/vI/iBoZkvKg1BTvctX/8b\r\neCxVh1kzV5OufUJlV68KZZY2BiAzMtE3HJJp1wE/lpeI24oExpLuaOrt5fuN\r\na6LpepCNtJI8wrACKHD7NC1u8pIdQjP665k=\r\n=rEJZ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.4-00bd3dd0.0_1656063046714_0.8972121143887462"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.4":{"name":"ipfs-grpc-server","version":"0.9.4","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.1","ipfs-grpc-protocol":"^0.6.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.4","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"965f5a4e00254cee48fca2127d95209deaee09cf","_id":"ipfs-grpc-server@0.9.4","_nodeVersion":"16.15.1","_npmVersion":"lerna/4.0.0/node@v16.15.1+x64 (linux)","dist":{"integrity":"sha512-AouzMdpWwQpwlWmNd13BFQX/RydI50RPsryP8z+gF8M4D85rVLxs1+Q0fToyo/JlmtrNN6dKNnFiQ2o8Kjoh/A==","shasum":"2cde689c611ed509b81ea3d93aaf398cf74e29bb","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.4.tgz","fileCount":41,"unpackedSize":41877,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE4xj6ITT0S7UlTnZiJaVs8GY6XKLuUJ4IMxTzZ+xqtsAiBH6JVnl4+WVAWOfcyRgUL1F0sGCANbxpisqW110+Ku7Q=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJitZEUACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo6hA//Sea83lja8d2Qc+d56GocqtGePOZcO4lGALyw9H/D2HOFm6bp\r\nOt/m3YAGETQHQu4EbLkmABpngXvSPeepRvRgsnCGKYo8FyJkiYmRMkC/G0vx\r\nIHPTK6ut7ICZiuhXguIppUMb6gJNTLKViAzFAIpTLM7MxhEgZkY5eY9v80ZB\r\nKHOFUB28TMpl5t0HFIIh6tHKM3ASkLpM/ysBlFVn2Gh9g2NfiMDy19Opoc1P\r\n0qwZZj/O2yzhIopgxPNaoHyyQW5QCKXLWOJqiSLmwFvf4TTOzuvTQt/eNFEr\r\nf8oFNuxhYvvosAE1aVuyLx+mHnQ2jVhl9qGaGvELViKljVXHNFrVBbXofRHM\r\nFJUe/mPAnnM+RhHNyV+gw0H/wSeRIfw/8wT78iT9PDNfuDy0PUmc1Q65TD3q\r\nGFKwFnq6zfbVYCM/OPzLKPRwLXEUzKiWK+Y1eQhcXgZBPYoQnaL7EqicOT7S\r\nwaNjh4a0Kn0YPCLdvn2yxBRB4OVmSEm/fhL+uW5uLlo901bAXA/HXOmaN6m4\r\nDPyDcQNp0Mc0Qm4zFsXpvbFHCTh6T9CLHKuQIUDxiq9iMMAvBUc6yj4J29bH\r\nqHBw/b/fgFQbAI2FM4SKbZmby8s79T4dE0O3CXQquG1frhxz8jqPeq9LrmfU\r\nt7/kBERSrN6BWdkIXaRJ5//ro8xdrstChoM=\r\n=cswE\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.4_1656066324688_0.8556999344386051"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.5-a05695fc.0":{"name":"ipfs-grpc-server","version":"0.9.5-a05695fc.0","description":"A server library for the IPFS gRPC API","keywords":["ipfs"],"homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"license":"(Apache-2.0 OR MIT)","type":"module","main":"src/index.js","types":"dist/src/index.d.ts","exports":{".":{"import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^1.1.4","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.2-a05695fc.0","ipfs-grpc-protocol":"^0.6.1-a05695fc.0","it-first":"^1.0.4","it-map":"^1.0.4","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^2.0.1","nanoid":"^3.1.23","protobufjs":"^6.10.2","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.5-a05695fc.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"06da5952a6d61e890ae37d305b99a5f174a1555d","readme":"# ipfs-grpc-server\n\n> A gRPC server that runs over a websocket\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes |\n|---|---|\n| 0       | Signal |\n| 1-5     | Header |\n| n1-n2   | Message data |\n| n3-n3+5 | Trailer\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning |\n|---|---|\n| 0       | START_SEND: Further messages will be sent as part of this context |\n| 1       | FINISH_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index   | Meaning |\n|--------------|---|\n| 0            | 0: This is a header, 128: This is a footer |\n| 1-4          | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.5-a05695fc.0","_nodeVersion":"16.16.0","_npmVersion":"lerna/4.0.0/node@v16.16.0+x64 (linux)","dist":{"integrity":"sha512-fPi1+XSVsA/auiONh+1ZcNGltaT48fUwednzQvCCpSNBRz54ApOdRQ2yKApMGY9kYbMhppV2Fu2Fky2WeZ4Csg==","shasum":"2dc497b06691a6bbf60a2ab45850d797870a2163","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.5-a05695fc.0.tgz","fileCount":41,"unpackedSize":41921,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHslNBVDyx7MjCwE4Pzic2aio/V6GmO+mamqua6JP2PUAiEAu6Es0JyLYfFyx0lpVjpHlnkpV+67gNEeqeeqi8U5dIE="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi2AGJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrHSQ/+OfUao0oYQzY8F9oSSBQZ4ymCLmCJzGAz2Wl5PirrWXoQCdbV\r\nP1WkEQ9tSmBaPOCDUzIiRD8CuzNkJb0bBx5XNMW2D1Fy1nvNwHke3C6kgSYs\r\ndCGSGCff/3iyiIsJWtC6NagCSpA9fhd01/IVloFWVH353nZSO1kq5pVx7G0z\r\nJcZpAIcGnu3MIY7Hfn4BP34a0tLD1SR7VjeykxhTH26urH++/VWw8hFnHT0K\r\nIiy4rgXOB51WXYvMWWQT0MdAat8C1lsodbFav4P1kDSk6o3NaZpIQjGYxgYN\r\nqe5owi6iugtg59FZeDPjvu+KeZ9tWBpoJqj+VJM58xuXELmllTw7AAoudndS\r\noE5D6DBGpaN4ljwETED0LlUYz54FFd1r4XcSXBbId4BPWaulqmSRpM0zkAvm\r\nPQDveNbXV+YqPCbtdDmeBrdYvkBif+TK7ce0XC+RyKrHv84wt35ABcBqM0P3\r\nmtvwY7VhtqL/aSJBoQlDd/2UI1nv/hDdpWfcVaHHZVu5Gf7+d+bb1X6ezr1Q\r\nxtFCol5f/8T7CiuuywBz+ABWmd2ycrZlMJPcHJXBhX0QJW8tCaS/c2bdHvD2\r\nl3iiC0QdrtUAd8GWbLGj7zpuob+NsFH2YwU6wc9I71S4s52+VreSqyOkL0PX\r\n7eT+LrM4bswBNB06QqcH2MP8WbJuuS/5iEk=\r\n=JU7O\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"achingbrain","email":"alex@achingbrain.net"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.5-a05695fc.0_1658323337733_0.14906384452487842"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.5-39dbf708.0":{"name":"ipfs-grpc-server","version":"0.9.5-39dbf708.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.1.8","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.2-39dbf708.0","ipfs-grpc-protocol":"^0.6.1-39dbf708.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.5-39dbf708.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"a2f1f57d7993d04b2d19c3d7ecbeecc95a54d2ae","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.5-39dbf708.0","_nodeVersion":"16.16.0","_npmVersion":"lerna/5.4.3/node@v16.16.0+x64 (linux)","dist":{"integrity":"sha512-hqbyfTvJ/jihryrngrLVwKe98F6aLuNsZ/yP8TzIxC0/xINbD77Bmb4zZ9jYJeRZ8jqUPmavC0tR8mxj/q5FjQ==","shasum":"d3d485a6867101825d44e684c043a56b283f177c","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.5-39dbf708.0.tgz","fileCount":42,"unpackedSize":45347,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDZoDtLd4pEcCFZ70NUZo8yBkfuQHLwFL60og0RTRiuogIhAM3wD4xX+TXCMHaywvP4m0s9pVz1MoPpFuYe80RcL6d+"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi/WDoACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpTKw/+I7GyUGpbsyuTM+f57kNVJYS86CQ9nwNqGkhJt8KJFjl2/1zs\r\n3ec3q1QGjd+ZNqZcjn/OuIg7dYJ7UpeLDEzolt/dSMdOwGbK16tXdXuDrECA\r\n1O+SYoud+YcdpOgPr+X3xBjfrUejdJ68M1U+a2hCT1H3CIRD5vI0G/Qkf0ds\r\n5IGBKW6NwZW/82ea9cE5ezPgURY/kamVP8l6Sd3las+MzswjrUeq0akY0AUt\r\nIijCGk75zbjodaCdlBHVA03ud7g2ebTkUa0TuHrnh7SSXlNmr5GVqfECwUPS\r\n8PoVBfgtgz2Uxph03N66h1zoNvjxIJ8LbfN7q7H4+xyXnRg6qzdOPL2MiXMR\r\nawkZ2MYktszjzJv7MGCs/1BVuGgWP0snCWH7m+VjeUBKV/8SuCSVEwlSv17T\r\naoKBALcS4V9LCCvAKs9LETtYuDxDgmGALjQGpJbQGnFvqRg7POPV+3+1nfNM\r\nqC+frQNvxSoUutgIs4wI5fPLzTNAP57SLWCjDgxYqbELLwlSG79WE9r2VDCd\r\nNtXzOsC3UqfG2qAwO/m5ARMJEv7ctOkZYlRvsZu5LmJ9f0zyKi4XbgaRQlIw\r\nzk3aTczRPk4hi4G5Q/H17kNFTvmV2IIkC+VLp0CUWVJb2JUvkn+GP3mhEFnW\r\nUhTHe2fePkpxVa4pslUG6LKk1vmsWs8gbI8=\r\n=bfAn\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.5-39dbf708.0_1660772584091_0.7249749986154903"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.5-8f351a89.0":{"name":"ipfs-grpc-server","version":"0.9.5-8f351a89.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.1.8","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.2-8f351a89.0","ipfs-grpc-protocol":"^0.6.1-8f351a89.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.5-8f351a89.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"59229f179fc680ee9075d2cc8deeceb7ff1b27d8","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.5-8f351a89.0","_nodeVersion":"16.16.0","_npmVersion":"lerna/5.4.3/node@v16.16.0+x64 (linux)","dist":{"integrity":"sha512-Y2Bn+nF+VgDslISoJ5kWtji7myr/tx2Nmj1ZiNdc1wOjr46vh1nfhNJHH0qYpH7PrP3Y+guVhe8U7wxHBIB/5Q==","shasum":"487d4a6a5848802859ad470f0f2bafc8019d3580","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.5-8f351a89.0.tgz","fileCount":42,"unpackedSize":45347,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDIOSxcbOUAcIu1SEPWZONtwp7im4S/8DiJ7BevrTYAPgIhAJeW6BWA2pLCew69y3KPxpG2ppdZ06i5jiFh5kD6lvFK"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJi/XdgACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpiGw/8CfnH3l9P16okpCfozdINfdRjxOjr8xZHJbU8QOVN5rMCuMNS\r\n83bHxdbF4t/371SgpGmsJYzfXK/s3attHF6W6RjEf9ncXFxF9OPelVeUEq7g\r\nR0/kEXUCjKEXf480Mf586wMZhv3PJkdg9p8pY7vG/syYwLsrU5SaP7RoLt49\r\ntVSXAWYy8mENPiS/6fez6Ly9FnB1Qogf3u+xk6fV8xOycQGX2jnLElO6pO0h\r\n8+qEZZkVyeDpTHbNrNTQkNkH0C6FCjAHXhLFu6EFmq28jxNdQet3F5lNCQFb\r\n5WFZMPyzYsvpnnZtw2hctFhyx12ciU5nVt2/mSscV6lcZYe0zDt8rdJ5dMCR\r\nZ+83kyx/yjCf2nEVLtiiLmxbQpspX6fYawI9nEzoDpKCuOI9opsvCuxvv6wd\r\nJKMuntwKY+TJJ29RMqvWmFTs8kX4YvCLmgOBSApaRRtdmp/SXn6HHPRu2Jkt\r\n6j04Y2kh2M5kyruxpIv8wrrDknnNgtxw/HCBd8cWxchYRZIU3xytnpR1IiHR\r\n3h+ih6wAxi77Fgl0uI9lugelVFqTApaU2gXRX5Tgvm+i4TotKPskxe7L38ug\r\nZlRGXwdxWrsQtMaI+8NOaXWtvWTFD/950dOs/RaWPZrsYYmOMZhQB+/eJTyO\r\n27XOp5NzuAjJ5ZWjrpZAKvUh2IK6p1Gweig=\r\n=L0eB\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.5-8f351a89.0_1660778336517_0.5200484781686927"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.5-83f9882e.0":{"name":"ipfs-grpc-server","version":"0.9.5-83f9882e.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.1.8","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.2-83f9882e.0","ipfs-grpc-protocol":"^0.6.1-83f9882e.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.5-83f9882e.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"368c95b50c87246f0c5b143b79deaa4329d0727a","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.5-83f9882e.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.0/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-1GGmcfVYg7Xrmc4e6YL0DGEyKsZSqYEmot+T+jgD9y10fgG6wAgnpn1WUa5NlVyJgIFIAe8b6mCBIBumfAe0Iw==","shasum":"dccdc2e0b6ec3ddc7280caafefdde0b2587588cb","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.5-83f9882e.0.tgz","fileCount":42,"unpackedSize":45347,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFUrj+gKRm7gxraz0iHM3IHUaJ0LkzOI202rlqkLCvZMAiBakMJyacEmZvIIfNv7xaOZQ+tNa+wq+KhMF5M1pe0/0Q=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjFy9gACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoA/g/5APrWhPI03K7cnN9lEArc1Z1jxwAKoiOPtr12BI3srTzy3xjC\r\nZLGkVdEedxjEp8xnVO7LmHluRX/Pm3C2F7Qb3gYsZDVWGXGphEU7Alyr9oAl\r\n+9VcYbwJxHo0wa+U3rdJBbkH+1TMNlEp6nArjFC1Zy6uVWpiI2ib/F4uce0D\r\n3VnZKSoyyIFxDcyr4/dCm4uysLN4+7kMgO6KhyF0Cboy/PaIUNSpwfi3w1Hj\r\nKFM4mq+ICpw0M7TzgakrHBTM7rsPLGNy/KeVb9F5gSd7p/O2PC8GYLg+FDQi\r\nxFwazmJTOlrq+Z4qR7ekUG1b//x/JN58rI4T4zWA4EYV/Pf9V8cbB9ISaGBn\r\nOn6E6v9CSg3wzDn1IYXQNuqBZfxoC52vJ0hry2SA7WeB4qw8Fh9dWtcx5uLp\r\nj0B3zmGumEu7W2QGCywM4flp9tNgC4oHZbePsd1LOFFiUpbi0HXHmUKIVAkh\r\ne/poFfW7bY/2Y8lHOx0dAnSAKzwomGZOyZHYPMLNlSIv3T2rHKoGLmqh/Dnn\r\nEijTLqaLJsLpGAqTJNsi9inMO8ElV1uq9r6DLAplozqQKhtFX3jUJRD4qX6x\r\npuQirF5n/1cWxgRh4TIEgovef9VZgFUnPi1VIAgwR0xFhYWOo/dj6KPoxLye\r\nVg0h66tWG4yuDYrS1XPz3yAD5A7ZZbt+yTw=\r\n=xbJP\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.5-83f9882e.0_1662463839798_0.8691159188760342"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.9.5-051da161.0":{"name":"ipfs-grpc-server","version":"0.9.5-051da161.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.4.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.11.2-051da161.0","ipfs-grpc-protocol":"^0.6.1-051da161.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.15.5-051da161.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"262c2c4e56b8de0c602251e9ea0ac3546fd2e28c","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.9.5-051da161.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.0/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-wPUw1ySZqxc/dlfqnvZAKyxgszvexbtNL69738ojh447CSK4LCDpoDRY2HWyO6lHhcqu8Bp+4vP8xbWYE5Os7A==","shasum":"7367cbc7e7fe743ce175a6f0a99c9e53a0eca2f6","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.9.5-051da161.0.tgz","fileCount":42,"unpackedSize":45347,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD9+dQV9wZH8njuj1LJiKXn10l+Pqk4DmOdPNQPS/LVgAIhAKcULAYRY9fHOlUtUV4x4qTy+UUNPrcGKOL0FDPCMcny"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjGJTIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrwUxAAkaPj06QF5x4A7O4JxXe4HZrRZeaVQrb00gYRJzKFDJPciqgJ\r\nTSKH5+tecQ40Iga8Sjez+iOnO8gqiMILQO0woHQr14CKV2ZmyUsd4W8oJBmB\r\nAQVe3GbEvVmiJdhUuTt3wEzpMrGSowb0Edw/sD8qRAXwN0AAOtk71sdqTEcK\r\naWTEzuBWsahA5Cz5l4bNuHv0Gi+m0qfzaAa71IEuWL0cxZBVfmpMUtKWwAAK\r\n8cgVlJF3/2O5z0n1tUKL9xpynT/oIj1r2HqoKc1mOeXQEsWHWf3cEA3o14qI\r\nvK2uUE9mQfUcBNWDmysjxDrE2HAgkWjk3L1ateZkCiYs7O/Yh8GfX9aXqBbr\r\n3bVQvWUbo+CGUMbb7RFFPAp8R04r3ZFqEC8ElSB6saxjoRKjxXSomVc/Ujmx\r\ny7rlY+OtjqMUxOt23L0p7Y+zNmKq6bJJC73XXCFtPuZmFKf5TZSFjNCu9U0C\r\nwSo21D/O6n0gcZhNhTF3gNmIh23kk2EMo7XsTahBGL0MIQr5C+smywaSz+60\r\n2dKXxz2UaGooB9CEmb3FFlUZX4YKvCmGAjeN+7KvjcLankFtoyxn/6bDlzYt\r\nqG+bqiTSdZdxOKEQO1S1bQcLXiwnkKCD9OC6xjT2k9OcndrL7BwvmYjFvyFS\r\nhdjQqoiG+/ehylrMVmsKFAONBPR2vCCssEA=\r\n=ze6G\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.9.5-051da161.0_1662555336383_0.146697020626525"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.0":{"name":"ipfs-grpc-server","version":"0.10.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.4.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.0","ipfs-grpc-protocol":"^0.7.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"89aeaf8e25320276391653104981e37a73f29de9","_id":"ipfs-grpc-server@0.10.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.0/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-QtH61sm2ielbeOJRECt1+2+luFWEiAbZSsQS3kA9JAJ2ZD+9ReWjT50fP9Y1B8ejfKof+u/jvwQ795vF7FNdUA==","shasum":"d0f3f7ff098c134cd5db7fd97bfe9451e1151d5f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.0.tgz","fileCount":42,"unpackedSize":45304,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/MFNA6t3KGX05kU8VWpsUZ7clr27GBb0hAozy+AtRqQIgbO8zQfwIubDSoPTVtNanbv6Sgs6iDI2EyajiFFp6ojo="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjGJ67ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpiHhAAkJumV+63iCPxhT11LomV3z8rCqgWRzh/K842vgB1zpt30w2M\r\nVlUBJKWWAcTeJpsYrwzCG1mBwvMQD3xzHAVa3/8ecUikLEu2Re62wqiFY9F+\r\nvPjtdjCd8O5iAY/FZUf7XD7K5GG5cYTlKB1TzXicN0zEcbtjMLPHKrEfbo3T\r\nl96xCob3SWdTTTeoGldNPwPnQqNj2ojRbFzwvQJ0UEnEWrAso7yYXg7MqbGR\r\nprH8pNTt1pUR9IV9bH9mZTjqTCwyeBhxDFrJ+88CZ7dHCqTR2rMC6q4sGFKV\r\n3LMMBm4fgjXNQg8twvmbshnjbdsQxP8K1S8EdjQCeuiEJ1/Xw1sURlZGIyB5\r\nZYIq9q20dcOnFkp0tbC5NE5z7y4ORYFFuSYdcKCU4x/5j91pTuV2Aw0A7UPb\r\nP53irbD6qegmDk/o/GelOE9k+H2j6zt6aItDzDLk2JZS0B8W5pduxeD5MAkj\r\n+fRAQT3370+lKmApwbJ2TQck5vVoZFuv5sr8qyv9o75dWKu1MP1v8Ui00ldC\r\nnOkDgjEKC7KZQmHVy7CrQo5W7/OVib/X8Ys7B39yZ9Q3zK/DfhwDCZ0jd33V\r\n+btIP87uWMaXFgRjT88GZFWJHuQ9h/NDt32eKki4YwDq884t6jDEcBx72/8N\r\nhWZLIkoKgu387tXszPBa3iHxejVOnXYlPTQ=\r\n=0HHJ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.0_1662557882865_0.20108553480685587"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.1-b5456882.0":{"name":"ipfs-grpc-server","version":"0.10.1-b5456882.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^10.4.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.1-b5456882.0","ipfs-grpc-protocol":"^0.7.1-b5456882.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.1-b5456882.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"bc139649f4cd3840696282fa6dc6b241b9ea1833","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.10.1-b5456882.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.1/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-nn8+Qx/owewz/bBd2bVxvQaPl+eQGCqT/H9BYaFSRUnOiOSfkVS7180u8dVYc7X9mpcDvH5FWGZtsd8L0vEtig==","shasum":"2ab44ccc5138566ada3e560a85bdea36360011ca","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.1-b5456882.0.tgz","fileCount":42,"unpackedSize":45348,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBr5sqHfJBKLIV2XCLyaWJGG8fwhQWFJ+8ZsqG8siWj/AiAsdDz8n4q7uKODZBB733AnGaNzoBLapiq8yr2pzOIuPQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjJEDFACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqC0RAAj1b0kv40P4z1xbwSTuijYK8GWdyBGJMNghcg5uJkNCKQQ1DL\r\nq3rTR5KKGyDlGQjr7zC6kH6Py+G/iv8olx7Ms1OiWoeUcxjlRThu395Ff0x7\r\nq0o0o12Zctaa4lM6wgMoQ3dOWuxVQms9e92L+SBOtJinkqUUq6L5O1PQrvcy\r\nsmQjroSvaDdBs4hecx5VdKxmjNLZoXzdHODGtnF/kj3yDn6FbQ1s9feUzvPS\r\nSxi916ai4sL4oxKbSEVuA9LLp6fXFoCBiQ6gDQVv8aU4qT7Fwvk3wRXfIj6l\r\nLa7PExYc1T5NoxXiql2MoWtf//dJ2JfvTN3dQZCQKN2MYD1ynTQF5o7GFDhx\r\nCvrvd0znErlZjNFtRPGehWJnqlL17KeRvz8Fwqgp+EF6sNmUqsKAo3cvhT/B\r\nVs0aR0xcF5b5/lgb+XWNWWiFJPpbn71alntNZdkAgUrTp0/5LuJfr045nwRx\r\neBX8HNLzVHDg/RlVni+VItTLYptqteiFG/aT1O6/b/0ShJlpzOuyeuvrreD6\r\nKxukmyPghZyXz6Nc0CiebTFfgO/W9SdNbajjovRodrF2L7j7eJsmrlWcOyFB\r\nANQX0tLIrRl0h/uyEk5adxwheq3aW+AJHNCMVsnQJUcRbx+d2brmCLQHTWHX\r\n77FPBlWbzWUOVDCE7I3P71ee0SOzZ4JFyeo=\r\n=3Dxv\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.1-b5456882.0_1663320261268_0.7719932958983642"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.1-7c676f63.0":{"name":"ipfs-grpc-server","version":"0.10.1-7c676f63.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.1-7c676f63.0","ipfs-grpc-protocol":"^0.7.1-7c676f63.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.1-7c676f63.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"90802df6c68ef286b155c31dc4f625a9f29ec7a7","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.10.1-7c676f63.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.2/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-GkcauzHkyGiUPEIb6CjeaM2yRlPLQuhDr9u7oQnZDpZEacZYOBdoLep6YpHvb2hwZaOJJnKvu3Vdh6AGfH9qPA==","shasum":"e04a869fd35cb2013ef13f63f5148770272c5d93","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.1-7c676f63.0.tgz","fileCount":42,"unpackedSize":45336,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDwDt0Ojj5PvLLHdL90Ht4FOOTDDkJFyyDk4CVO6fW5LgIhAOfgj9kQUzpJhPHCxEQ4/8Onay5lyL61A39DPpdB+cfJ"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjK2MOACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqqWg/7BO1HLMVoFhIYg9RH4xq2UiaV6yUIPRuqGTI5Qk289tXibS24\r\nJXRmr8nPMzKnIbVI0sIK8N6DWvwZwl+U39ojPJ9V6PmJPgy94zZ5VXCLtgZT\r\nyBeJppLp+tVxlpY4NGf1zRLM/Odq2nck8ZXTeb3t7hDvCqY8zZnmWo5Eax2B\r\nu/0Anrimx1xDYXmEXgK/OImVzVUT3RQn2leohYfxxfbTjlr9WzL/LTFEM5Lz\r\nTxKfhkmWFPE/oo5N0cOVMLTZAIr7ZuE2kXamJtpo2ZtQzpcLWn8Us4UsilJS\r\nZSUn5iLsQBEJtEiTyFVVI47tByizilCBYTWVn32/Q5p55kWCjOICamVUfweM\r\nR2uROPmK4W8ZIc3g3I8bmou38rNFedUB8LjzfRfl/CFQRj+3GB4S9xXFj6Fd\r\n2bMKKsn/vjPVkRurPtMvJMXgty0JLAMLL+4h5DCr/3W/EMpiUGgQDD8Y8HmM\r\nogWi2b/1MqQvjV23ohzCqsF1ryaWsMZ7gwQ91Xew436mq/QhyZ4h50vPxyIe\r\n+pDvyQzv2d07W1w3JeOoIkKx5JV4jzrYMqktQUN4Uo0hodjaa15pfJXQ0VOQ\r\n7WRKgPgOsENGNZ4GNmt7dq7iaoQhrCejC89SQYkLKKc2T1TEdFbiUxSX2QkR\r\nGg0mmD0pzVNo/tKq9mrtc5u0tOOVEpY9quY=\r\n=y1sl\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.1-7c676f63.0_1663787790476_0.5820571454712713"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.1-2a830bf5.0":{"name":"ipfs-grpc-server","version":"0.10.1-2a830bf5.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.1-2a830bf5.0","ipfs-grpc-protocol":"^0.7.1-2a830bf5.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.1-2a830bf5.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"ec3e046a48458e999e557f7adea92e304bd7b0e8","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.10.1-2a830bf5.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.2/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-t29qXlhF1GkfN+mWg2AWLbZkcAV9MUUt0YO/NYHK9NEZSj0r9Sv8Y+rdvSoEvx64ih8Avh4gJIVZc1R3FHt+gw==","shasum":"4a7f8baddaac8af0c367079d4e6f988a232b4ce8","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.1-2a830bf5.0.tgz","fileCount":42,"unpackedSize":45336,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC4vyt4pO91+Y5xA/pMj6W/UWRtrIIZwKrk52sz8fd3lAIhAIwB9La/am117B75cqNoN9QbfduhAPaQ5M4/0Cg25FN2"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjK3nxACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoCGw/5Ab+kSuqkPH3kDZmPcetfB/E1OeJbMaBl615br0Qq1G4/nPJy\r\n0wMFUvc4G+pWWc3isxVg1D+6mNWp5HUtR5TscuTFtP5zqYytA4wYTENZ5gUt\r\nQfFeWveX1cJlxqBqPSNqb3/eNSOlstQZLdEuo+E+CkEgNIWQWHdjcBOndhl2\r\nBcchnAteTh1uGA7g070B7+UAaJbq2zFbu/qtS6SVHpd0VNh5Vyqqby/IAbw9\r\n3DTuesz0NX3ZTsdpPDwVWm7Qah19/m7Z4Q5l6NvbYpenv6OTR1PNxbKUKpcV\r\nRXWTdkkUTy8GFf65ybpr6xL8byyhq7fRY7u6QWcxcR5WWdpEPWNaKftqM2qz\r\nByGBKSAx1mMmrn/lLi9Ig0P2w79ckWWx5gq9i/2uH1Cy1yDyG/NgG59E9sGA\r\nTaOLGYickv3PKx1CAACp0+vJWCLvjhktDaGhloKooGIHs7QQ3E/No3d0AvbF\r\n4wPQmE/eR4MFV2+NmX41Wjax2jBGjgnogCUv7G2b8YupD9V7UovCy37aXfgX\r\nkWoC6PvJ4OXjjJqLhegBl751zAj8W7+ZI8QCPRkUVtvjNid0Tk7ND+YiHPr9\r\nbpmUj11r8W0dYR3aC8cspT+3g/eZKF8clQkh/pkf0YbxjNlDUiNCUs5JEJ4W\r\nEzEcU3NbfulL3PSEu6gYxo8wkB3LvBmligU=\r\n=bp+J\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.1-2a830bf5.0_1663793649033_0.22087776235815393"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.1-7304a0f4.0":{"name":"ipfs-grpc-server","version":"0.10.1-7304a0f4.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.1-7304a0f4.0","ipfs-grpc-protocol":"^0.7.1-7304a0f4.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.1-7304a0f4.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"95735ef611dd7b897d3d939e512b6229757532f3","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.10.1-7304a0f4.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.2/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-N5+wNohTVhmytxfTNCmF2jY+qVoY7CkAW1jszRGyszpqvQlyXVuznIWz3z9F8kQZvXUppLJPwGc+7xPUjJg2vg==","shasum":"a524e3f6c78a7d5a46138ac1d3543d52b3059744","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.1-7304a0f4.0.tgz","fileCount":42,"unpackedSize":45336,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCtY3mA3D1QWlqe4K724qc5nqJ1R9iZQcZnw+RcJP88RwIhAOZsRyfFS3LCUyf4gxN5VBS/RtGUX1rdyS9OJHXpl50n"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjK3oaACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpYqA//VPtuOYKjEyI1lBTAzctHd6U+zfuOPq/VbmUY0HhqwhXKm8kd\r\nTFJurc9F7j7uZO5MXqH8qZl9FZoNgZlsHxem6q0vljNMt3PcJqXlplsivCEZ\r\n0u+txi++W5n4sAevyfq/UxKFRYJ5ehN3kU10ptSUlx45L4uqCwsLs8MrWB8H\r\nfwLroxsBaAu+FgKEk8Lru147iV9IIyKsuD+BEmFjXhbgflaNXa9dyavje14+\r\nzRNx+rchUr9B8PeIIs9CjucJcGBkQrLqbC+Pt1TJ0CjrEyBYDp2zD57wlTkX\r\ndlNz8If9sgJWcrZ03lhdpnxQ2TSfxkZIvbZB5bq+7osGuop2iOtJJNacEPEL\r\nS6JZTd9RYmyfrcaNwE3IRCmpaFf09aLjcR0HqajZ5/e80MDdkmQtOevyOpAC\r\npvxJe1bg5VkA2ta1f/j0WKvTlzWdWAh9YfxXRRELvnScksL4a/zD3xjCRN6r\r\nStlkehTsxcFt0DkjFXIuZFej5kNnRUTolnNaEKj7fAmJbOFkJF3szZ+swItr\r\nAoIP4GyGTrL2A81mNtE62WqzSBab7ZJOardV6+9/QGNaLDzlrK44mvQJv0lw\r\nFWIUXxeE7nvpBxjGm3DL+DKTBT/Egas6Ggm9wHwAir8gnayk/mqQwFjT053/\r\nFCfMblPqtgzTkV+Ma8LtXxgl7J8nDJcX5d8=\r\n=78I4\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.1-7304a0f4.0_1663793690355_0.1610898542853767"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.1":{"name":"ipfs-grpc-server","version":"0.10.1","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.1","ipfs-grpc-protocol":"^0.7.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.1","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"d1f1e75b2060c5c2e64d133a7a6bbabd2641e5ef","_id":"ipfs-grpc-server@0.10.1","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.2/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-9aPjHtkLvhZhOHucUF9+iUhdFoW/mcsrNWgEa3J1xJ0jAmFTTk4psZiViFbSLVjpFgYwXQExavZQj3Z/9LDjNQ==","shasum":"67d464b04ae3a88416dd7e7507a816f93044473b","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.1.tgz","fileCount":42,"unpackedSize":45292,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEL6Gdkx34V7BvKXN6SlZuggoyevsu0qRD7mujWt7RGJAiEAi7dC8k9ENhqSM/C++JvTBlY9QtwqpfTKpmG4UOBZIaI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjK4g3ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmroDw//V8FBQtlHFADXEiD7tX+i+TRPpWF32Ub0LZUpQMLSfBzykTe0\r\n/cCKBoiXXabRAMHTrWBvOcKBWzmU+bdVz2oEy6PXxlLfUsSPLbqFjZ8BfjM0\r\nH8SWJaTixF3kE6nAZS4xEuTIY3mX8vIxcqaEdGGbt0RhIaJeUsVKOUYYUisE\r\nHEChu5A9/wFCy0YN1bcvnPUUQdMWmB8JDCfWcL6GRQwKfGh2Ba/x8+Ed/N1/\r\no1MuM5+QFbsSuktcr0tClL58FNq5CA9+CF3MfY/0YwRillDsx+ZflEkDkhEP\r\nIefhisESnMG/MHP36CYl53NNPpoWMJxjP1n+LUPcT9jQeCiQThgUWhlqA/Vh\r\nRUwbRnDT91oINw1YT5GRNlQo7QEd1r7ew++QKG0ok4PuHeib+n6zCuOthj8D\r\nog7MVE7i5oUtyhnIB8r8mkzC3btY5ARIBh08P6Fcvjsl8kid6ZrhK9AFLRIm\r\n1IpuE9teBkPSqHovOSYne2KwARmnhTPARQKYg7pk04y50TjO73jhDcsC3cDe\r\npjodgIRBjPz8nB0DgQ4CE3tIVMw/hRgY5ZaRUW6i8l+VdLAnencm4d/awpzk\r\nGsCSerKaTN+dKHTrXR4IqXfCzYa/66H+162pjEs5Psol0NDMXLUrXljsmWFp\r\nAFIq1ex4h3TvxJUAVOvnSggRadDXc57Vbu0=\r\n=ckaq\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.1_1663797302967_0.1939370489322103"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.2-d75e0a39.0":{"name":"ipfs-grpc-server","version":"0.10.2-d75e0a39.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.2-d75e0a39.0","ipfs-grpc-protocol":"^0.7.1-d75e0a39.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.2-d75e0a39.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"4233393ebc1f8526290235c1b52f4d459ff96e1b","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.10.2-d75e0a39.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.2/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-IutsP6hHwkR9jeqq7B3PgdyFN/GPTR36uYDKjc5PP3wil3et4zfwnKNlomptpeImjyc1lLu/2z5E4OCam/WXYw==","shasum":"e734e9cc758ad3a47e7a3ec3461a56eef1a21503","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.2-d75e0a39.0.tgz","fileCount":42,"unpackedSize":45336,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD7xInLGQBgE1IML8Wp4c1pBH88dD1bZnCUcsS44vrYNgIgRf3nE7Y1rOFU7DUpeLj8TX6Xi+IKRHDchlkOtfeHHcs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjLCJAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoLzw//X3cYiJiEKsf1CBn4rmgr4W++inkOd2BJwox5cYKHEnzozJed\r\nsWYVr0d6RFKa3g7tO1B3bJWRzs83j9PS6HM7L4a89qxme53/1PCpV55U0GLS\r\n5ciEFSkH2PFKid1ECOU50hUhPuJnKGs89rZt9kqvnkbCUR2CkETKUuHZQrsc\r\n1O1O2YG85c0yh9R6JAgV+7QAuGaZHy8IpomAtcmXDYBx9WQZSG2wICt9KvAT\r\ncCXVP8SoNCMhpQa1LY7QkfUB5B1WMMffwQMtMSCfvbMtiHVbH1+2MpPwhkGf\r\nPzloo4PcTJglt0MIUbDriMLSvadTuEVW+kl69De5u7SQHr1hR0Yu8UiGpiGn\r\nh257hLrqSt9NdzZ1E2m+Epc8lOnp+/BkSgb4qKR2hrmx//o4n9u+XmBfheXy\r\n4anG555bXsUsldbUqxSh1D/ri7dnvPQW/6VDDe3q+X5scnvwnjkLkU1aPehh\r\n7YR+5DtrwAS5SCjqscoZBCjlEX2kyg2bSYTQ37FF3EIjHEgzsHqLH0n57QBM\r\nn725enYA/1Bjjib3ii54o2IFQHovK0YLybxqvrd33n8c9YdnUeniKan+agl/\r\nWwuYASZCxDezo7j4y68Fq5pBDnvjyK/5JiL9KJUAc6dbELF6SozbduSax6SG\r\nxwdpT7hPYBmkCAeZpoD/UIcnPpuKfmr2Ezk=\r\n=TXPN\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.2-d75e0a39.0_1663836735935_0.25572436551754985"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.2-d1b0a8a7.0":{"name":"ipfs-grpc-server","version":"0.10.2-d1b0a8a7.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.2-d1b0a8a7.0","ipfs-grpc-protocol":"^0.7.1-d1b0a8a7.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.2-d1b0a8a7.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"de2a2b2cb3fb26e858af2319c63296a1ca411c25","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.10.2-d1b0a8a7.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.2/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-IjjscqVtZ2TfzmI2M8VYEyY0N9yjSQ4RSYOMfG0HeS5w75sdvXZTTVJCvRJ4mabedwAQM+I7qi2UKhBsK9nXfg==","shasum":"9c2696a06bcf69fa576296664f71baf4575933ad","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.2-d1b0a8a7.0.tgz","fileCount":42,"unpackedSize":45336,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbSOE0Ei6+1UJpZi+0ImXaBWClXid2QOim9ubkSQwjdQIhALxBnbAVi25fHkEdF+1/Qxf2liDyoXBNFeSeX1d6z7U2"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjLDvxACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq9QxAApBqlpLKmnIUDcAGu2QxsEPguRy5uNbBH4SRme4FnqIUvRM21\r\n+6jeHxAEiT4RMz0NbKDqyjg/10dJA9PQCrLbgHzvdJugrMlux0DKrcaNHMjr\r\nXITQKjY8wpoCydvvsrpeKgkBU/6Tjs9KyA8DIA1XcvQDfjygz6abwTv125yP\r\nAkMLbw+PoYVeR01j1pvWDAQOGJ4wZzyOoKvfcuHdEXq1lanYQNRkX12NT3Vi\r\nE0yKwtYEn8kYfhPehqmzVzGjA2xayPxkdg5fXrNVTVra7JVGcSzRjwiGYdqe\r\nCB9KGuEWP2EtGXClfG465BAeo02jfWKMSES7EyQTEA9fM48fNzaQ7ASCcbXI\r\n9JN97DTVWTsg09mq7TYKjvtz555iDfx0Uc3iumFZlscAjYiNTnvIJp2Ijx6D\r\nZxWqACCanIbBWmrfE//vkDWmGdIPpQxiPJpAvwmxEBbpDSh19FDBOCx9hVtD\r\nBhL6tE9E1FAoBGK6PqtlKuA9QMgocXnuCC9xVLUdJU380OSlBao65pZDTLIR\r\nIsUPLsG9l3jJ/qe0jFyfGPAVrWMX5gmnYm+bx+gcJCMPRwICNkP0gGZ7IDgr\r\n4OEbxBC8ZtiZRi1UZgEuQtkHRIoNGRZDDOsh9mjvVeZ7v4mlbKnZHMuo4ybR\r\nLG4b/kmfC8YcOHG3tsGk3jBmCxbLWpgyOfg=\r\n=GSKA\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.2-d1b0a8a7.0_1663843313111_0.9992502076403753"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.2-acbc1c62.0":{"name":"ipfs-grpc-server","version":"0.10.2-acbc1c62.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.2-acbc1c62.0","ipfs-grpc-protocol":"^0.7.1-acbc1c62.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.2-acbc1c62.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"60666473159284a7bf9067d10436033caafeef5c","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.10.2-acbc1c62.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.2/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-4rbAve/Wo5k8MQnVS0rExS2fjRUXA3bV0LorelqEdrfxG2PbyYpql97hahrkvN+yJs9491eT4AYyPpqyyB7Y/w==","shasum":"ce7ee0ddc68eb544cddb49032d3f03239f8d07bb","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.2-acbc1c62.0.tgz","fileCount":42,"unpackedSize":45336,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBs7gZcimrUA78b0XRHs+srrfY99tdYMVogOB6s7s2ivAiAmn5o4UnKg8ZfAzilQqqkha2l1QEgFUXtSruLsdpz7Hw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjLFxNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqmdQ/8CIV1DJQdmO40sjQaPv/W8NbV8z64/QcbpWeKP0WT8GlEQeN7\r\nWLHh/edRbyAccZcW/hMIttdWV/jkrO/0jW+Xjc9enenQEGR5cRIixMvdyEht\r\nXQzlhNaSGc8Ty4bP0Ub6z2prnw5o4kbvzrjaJg1gfA4DDN1ERd4bICbMRfSX\r\nNcy+QDO/rEKDQErTWzk5MBaDFso8seKOKxGI2Hx+fL5/26bVkb6K1R2RvyMc\r\nQdA+yrK9pI6MHUrmR5+X0u+KeVLQks/06+BssIJl8XcaWqXHcpZgtW5wHwqo\r\npkw0dzIFEJb5lxoKPxcqtGx+Kn1Z2FgBJgYd01jYB/If8ZaZUT8IasUajrRM\r\njrg0b4vTIoy0SXzk1tUCPzsiX/mTZ28FR/KLZfdedCB8VokBKjAtxVjfSaXZ\r\nAHBVYI+DHcjeih7oZjNWdCwZt4r888WWw3oiIZ5WPwUGZzW8jmOeArwKVyvV\r\ni4cNZm8aCWLSyAKVfFJmH8u5Vu4raz+iIDkFVWreA+BVhurDujxNNuqn5P3d\r\njfP1LrHk1ZqBKyymTYeucj0G8d/mG+bQ5myWcniodmdf5+o3A3lUQ9cRmCCN\r\n8PMRzmF6fbhTqZvYEyLWsr1rpRkDNkNme/sS3eh+D2OE85Bbq0P+dT8Vtpi2\r\nMMRDAF4eHtnm/vsO2mnD8DkAkuXHnRi3PZs=\r\n=G7UH\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.2-acbc1c62.0_1663851597436_0.2406719663688357"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.2-dfc43d4e.0":{"name":"ipfs-grpc-server","version":"0.10.2-dfc43d4e.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.2-dfc43d4e.0","ipfs-grpc-protocol":"^0.7.1-dfc43d4e.0","it-first":"^1.0.6","it-map":"^1.0.6","it-peekable":"^1.0.2","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^3.0.0","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.2-dfc43d4e.0","it-all":"^1.0.4","it-drain":"^1.0.3","sinon":"^14.0.0"},"gitHead":"4eac92ae987d3ba6007c4742456913c865a06857","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.10.2-dfc43d4e.0","_nodeVersion":"16.17.0","_npmVersion":"lerna/5.5.2/node@v16.17.0+x64 (linux)","dist":{"integrity":"sha512-5vCbCtsppcPJX7LGJWoJjvkoW8Xbn8LIQ4kVn8RjyiIZTqo2OaiHU8JlfM6Q0BCYwzsQQ/kHADg3qCjQVrLhQw==","shasum":"f8f6a0a9f967f834d8d95bb3c72d7928756cfab7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.2-dfc43d4e.0.tgz","fileCount":42,"unpackedSize":45342,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDzy/+4IL4RD2OROzO3LKT/AAK+Ve9PsQfYtDvbamYe8QIhAKb1wAWmm91r+OXQ61zM2iQNzu4gzRE0Y8kq2L2ybJm7"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjMbUqACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpOTA/9FTW5cfhQ35MppVtNzvoLVBqqV91GwsexfymeELTTG107oHRu\r\nZjzQWnyzm1bXB8uIUcEwO7Zk2dAa/5ZrjsG62bliRQvl307RAO+hrmwf4Y4X\r\nZkwdaaozf9DqPwF65s+Z1jNGIu7yMFxg+vedpzB66KkD5QwOUYUEFwbTFvuz\r\n+WliilW8+bPKosQHCeMRP1foxfGrDynwWs/dgOEodysJjyPKN8R3hIHw66us\r\nwUD5uP5JDDseSqcCsaEBjOkRmcBXTEJSaOme8yaO3XDIsQfRQgV+CXUXoSLt\r\noglWyQrIy6GlTuvmaj1rtQr4Iu585mDLGUXCPKTlqtB3DTjT/yn0ZqgJRB2w\r\n/6RTuJy2QpY1meqsBN5yksBd4V3zBh+dABsie9l2Asd7WM7g+EZ3pmU2gZA8\r\nzWvDB2DRWk7229mDfmN3+rrDdjgrw8HLg9qj7mIhsVWJzz4tfCtHNPTs0HEA\r\nDuxzPszV2PnSHTxtmuBD/rcA4dBwVWUHG6XlZL8x3yW28n0Z5+Vc6poESpSZ\r\nrdPVL3r3HPU3G9KVB4UN0H89GA/BSFzKa2ufyvCUxfOVV+dXG9UdDAYIxT/5\r\nquY3ae1VlPvNJ5o5i9wpBa5mpnjmeauvmBjwFPlOkYAch7txcxhziixLs0AI\r\nDSU/anb67KUettEPTRcNlyb64KSEQXYlM+4=\r\n=XX9c\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.2-dfc43d4e.0_1664202026207_0.38144896105422355"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.10.2-0cee4a4c.0":{"name":"ipfs-grpc-server","version":"0.10.2-0cee4a4c.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.12.2-0cee4a4c.0","ipfs-grpc-protocol":"^0.7.1-0cee4a4c.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.16.2-0cee4a4c.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^14.0.0"},"gitHead":"b44ea59fdb45d3e8532d6a2d5f670e2df46d36ef","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.10.2-0cee4a4c.0","_nodeVersion":"16.17.1","_npmVersion":"lerna/6.0.1/node@v16.17.1+x64 (linux)","dist":{"integrity":"sha512-Kn2UjFWEPmWyHCN/sndM76ibHwEwjzCNAzh9omVDKCaSg7h5PRd1hSWJ5TQ/oCF30T2ByE8QQJQoQfkcObR/vg==","shasum":"2d8626089a00c14b51bb72e4ab6f0e8d59efd69a","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.10.2-0cee4a4c.0.tgz","fileCount":42,"unpackedSize":45342,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICfrcLivR5LPn5Zsg70HV0tfakBY8arpiKyw0X/PjFxJAiA0NX6yCPbjmnrOUETn5Df+4+twpk7SBXBKMQWJBebpjw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjVlc8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq1FBAAmcoOZZhPe4JNbEQfc3FXoc11unDKx2CF2CUkB4REaBYwioHF\r\nz+v/YL6lR2hV8PqrcED/AEYbhNonkZlZKT/1DzG8xgM2R/fQzb04oebmKP/J\r\nCdLlKZGcsL2uh4PRz8C51dS9HJ+7OM8+FAeRJ1e/GXIb18A+Nm2Pz+ipiFYB\r\n/EFkbhPXWdtFIrM0Jr9OynarrV282jjkjOwZzJ2oRfL5yfGBmK66NxW/2W1v\r\nCOFRU0ObELBq9AizbLxvixX+UWMnlSVVwj891fB2me6leozhu0zOFP1irpr2\r\nOiW+QhmKd4AoJ7XhCfSi8Ha6Alu0yjdPIWoNZD7ZhPCexvYrI/dfd4S/rGQE\r\nus8ewY7MLoKJQCaurD7ibRHxQC01dW5YpaLNuw7PxUcptjXkEe+Jqdgk2of+\r\nI2G1EYBgsDtg7BG6ygLo4Yp113kf6PSiwM3O5wR5ihF8sgN+qRgLljDcOjBB\r\nWggFNP9eFBFETTO7CkTy3H+PuvrDNwIdlsORlaZ2DogTZbvZO3/8Juy7A1dZ\r\nTIiGwuQD6RcUNSiSPs/CqJbbqx/dCYQFYnT5qA77CUCf/0Dk9+ZFzUZ71GQU\r\n9YwShb0QQfBSwIeSZly1W3mCKMPzGPm8PUlVjFrfrDsdlZyZLvmcUm6IlOZn\r\nn57LxRSwYLEoA00H5QwC59F6OoztT2/G8oQ=\r\n=wjq8\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.10.2-0cee4a4c.0_1666602812004_0.004722001801176878"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.0":{"name":"ipfs-grpc-server","version":"0.11.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.13.0","ipfs-grpc-protocol":"^0.7.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.17.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^14.0.0"},"gitHead":"e8b7b66bfa98c2a1c0d0bfc19f698d7d00b6c888","_id":"ipfs-grpc-server@0.11.0","_nodeVersion":"16.17.1","_npmVersion":"lerna/6.0.1/node@v16.17.1+x64 (linux)","dist":{"integrity":"sha512-nqZ74hZE3GV2LEmNypmfvPDc1ZvyrPoSGNPZI9OVML67+ZjtRwwp+wZYVaHpeDrgY8p2ihRu0jZeH5/2m4XZhw==","shasum":"d918e20cf36591714ea58ab1d34972deab1cf07a","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.0.tgz","fileCount":42,"unpackedSize":45298,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC9LwWx4dDqjm3dzDw6DOfp5OE6Yr4v028L6b6BVnobswIhANN8uHcpY+7+mCn1asMOfgj2Q9O8xAp1pFqCupc9dYHY"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjVm1FACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrpYA/9GlsOnF0scqUINa7S+xSMuqriVQDJ4NMYR1CM2aOICOclcwdN\r\n9sCgFBz6/AlIVCTXeHvt/E5/dhC2aXZgb5IrBY6cQlS23x0MyDawI+xnZxmb\r\nWW/UXe/IIPc6XFpjMHcIy3JL67bwDHlvLt/K2ZLyusmx/X0PYecdK9Gga054\r\njsg7KoTUYbfl7S3CHA8mCrWfjBZ95FM5AG8nPUKOMfBhQdEQ9c1bGepjhfqm\r\n192yzjCv/9dxwCWWYLxoDmB8qYm65wxctNRLHM1jzhKgM2W3haWKqNzVD6be\r\nX/cHxiFQGY7ZXx3djpmJ0YzwaIyivIr/bztuP6UgfhEjLIbmKn9nCarx7DCl\r\nhDKir9ufyGuCQwFtCo+WxhbxkhfsStgradLyBhNbNUWU8TnfJltPd2ZIiGpD\r\n9lKggNueWPlzNEz5cdfi5A8dwESVFQNsZRUjjZx1EWhzduFOS2MCyG1sqOTE\r\n9hiHJh2TN6bERlbuSXSCJO00Uv6aJ5rHvSpeNFfoAzfDQ81g6/Gxy80Kh3R0\r\nbmFQ1MKDLoW6csQJ2d8CMhRyZTXnRGG01CX+ywGW/VKU6FVFKzbT1ta6/NWc\r\nKt9IhgmbFm76vMfUw/BNQYB3E5/KLHmau47VLx1zVPDCtTPqMObWwkd7GCRO\r\ngfwpWlocxdGkGcYkHeNrL2/AccETbMp4HI8=\r\n=V49y\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.0_1666608453187_0.5579803344261642"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.1-a77e40cc.0":{"name":"ipfs-grpc-server","version":"0.11.1-a77e40cc.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.13.1-a77e40cc.0","ipfs-grpc-protocol":"^0.7.1-a77e40cc.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.17.1-a77e40cc.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^14.0.0"},"gitHead":"a614528c55b8b22866bbdd2ffcde2e38eb5f578f","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.11.1-a77e40cc.0","_nodeVersion":"16.17.1","_npmVersion":"lerna/6.0.1/node@v16.17.1+x64 (linux)","dist":{"integrity":"sha512-gW+N/K83XJV0iUHgUXlv+AHvpXFdMb+7uueRC6xVzcgvlstHvQkxlOCm0dU6pkZQMCRdB1BHxMl7yjd2Olm7FQ==","shasum":"542f1768176b9086e73b7a3d17f93ec95ae5356a","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.1-a77e40cc.0.tgz","fileCount":42,"unpackedSize":45342,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDDKgIVY+7Lxym1KIoEp4i6qsjq6CqUrU5uVQD3pZwaMwIgbOe1fKQKxomVKvj55FwuWjzOrhtRYVYbkzUfjAUoUEA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjV4wkACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoNJQ/7BTYEprdxXCR6hZbLv4ENLwcs4VuojbzNQU6kk9uH9X/UhdTv\r\nSGFw6fnq8FoBjxGV6lUE89xZUwvarLwkxSkaefE2aocsemjerz8ykRn/VHa6\r\nRijtddEZ5TwNZMqFVW4CUKq3/S8piMTTRG9PQ87qtcICb0SHVkkjqG4Iyfnc\r\nRk9Ex/o6vAMWk1Z7yGpZYlsReRfdBqOM11kMW5wO1Zls+D0Z28zH6SmaB1kK\r\n/d3zm4EpCOm6HpgbgJ65hhg4aeMp9V+tA7sYmJpHbVv3fyBkSo6Zt7Au1l7X\r\n2RGJ3u8jElfanR/DbWMj1xvLee53wwoi38nVKb0KM20TQEzcwyE99P0+JYxU\r\nbvnLiGSkAvueKXN1/f7fINiIlfakBAVELpCy4kxnRIcjZIiM4DSiegURCNQN\r\nO3cpfQxxJAizZ9dlNjFM7UYOg82hO5qBsAz/2FFDu6jMijQyEGnNcTlWDSBF\r\n30fOpeIJwf9ULPNorBXJQBpDxN30nCKdJk6RQk3FAsfFcDXOJuhoZIDJOfCX\r\nUttTTUmwHoVwxceYwc5EtT9uvp4yMTq2Mo1FLVDPR8qkDt9OK91DSns2Lhj4\r\nh1AXhfnni9I/3wqvhrkwEmyrrz12OKcaw6FIFVi/Vi0TsYKSRBUmObl/Q3nJ\r\naqrvNYC3PdGlVNyDKaRZ5nTfCEkD95Gygv4=\r\n=3SDQ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.1-a77e40cc.0_1666681892399_0.4021209182658596"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.1-58e6f468.0":{"name":"ipfs-grpc-server","version":"0.11.1-58e6f468.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.13.1-58e6f468.0","ipfs-grpc-protocol":"^0.7.1-58e6f468.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.17.1-58e6f468.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^14.0.0"},"gitHead":"2a13d94cabf2e6ca2f631dc9686f03de6aa42447","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.11.1-58e6f468.0","_nodeVersion":"16.17.1","_npmVersion":"lerna/6.0.1/node@v16.17.1+x64 (linux)","dist":{"integrity":"sha512-fAB1QYOZ1VjDhcsRjOGvhA/RjinbN2MFPtltBD3PZwOlXGW2PfZL6iku/rR/l3pjIZULh5sFdz8TQH2YllIsJg==","shasum":"41695a2da146875aebf425cc58fcbb474a0980c5","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.1-58e6f468.0.tgz","fileCount":42,"unpackedSize":45342,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBxWN8zwbsjJAxkm7dQMlsMTBDhWiYNlJXf/kJvfruZoAiBmXD3+pu8g9n4mXxv9YPLil4Y81aTiIJa+FKBulIgJJg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjV5szACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpleg//bfUDHxo+oWbD5KB7d6nN6bbsYeyFUlwVg0umLCSxZajlOJJk\r\nJP6JOOnla3FIqE9ALbBLKl/kYOjtIOBzWbWQQi3ybzEE8hGqWK7uKr5MbXBu\r\nZPCv6dpVsezAvU1jiXuJ39vYHE/X0HoCW5lHUGmrQYDrqpx/6RdyY/KdHJNN\r\nxK9woJoyipMgt+Krh5fUF/cr+AqYFrNK+axGbEwxgnTH5cRx8iVoy8C9Ng/U\r\nuc+UzbjP5lYSjbwoR3d6Xl/WrEHtIUKWf8Z1OxoxzjpbL484xj77rN/9BNyx\r\n9VoGlNMSWNlZLwst/n2P7dyKK2VOUIUa7d7wFQfg8Kf/OKl5CQ+QaDCSZVmo\r\njqtGMliwromGboKx9wH5THBQ6Lsu/2PYwnhOVo3200RdgzAuzAm+c8fgeMvf\r\n9MfDuOtI0SAFrVuhLoSdH6z49QnQt5FhqbqyL6IbA0Y3EB0PPKg9tLU3cQ+w\r\nawV3ZvayDXQgrZe/R4kymPAbtwgNCA7ZxWnw2wXloeOhsqpzG5GQFgbReKJz\r\nxScXvWFGtfKGCs1lK4OgPXRaxEbZYQi8zppOzV5D1S0xJoj7O8FJXQp/JNrF\r\nSrUv1wBrllMPs1ZfNPbMXGG1JhitvVGrkbIEIjpyJsQOP8fKD/OXDUJ3rESk\r\nYiYjkGcfXNu2PmI4XDJd6qZVK8miqOTFKdM=\r\n=/yHD\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.1-58e6f468.0_1666685747459_0.19435135925038005"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.1-6ae5eb7d.0":{"name":"ipfs-grpc-server","version":"0.11.1-6ae5eb7d.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.13.1-6ae5eb7d.0","ipfs-grpc-protocol":"^0.7.1-6ae5eb7d.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.17.1-6ae5eb7d.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^14.0.0"},"gitHead":"848f64d53ffe001cdf63310c06e8f0ffe485278f","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.11.1-6ae5eb7d.0","_nodeVersion":"18.12.0","_npmVersion":"lerna/6.0.1/node@v18.12.0+x64 (linux)","dist":{"integrity":"sha512-f7ZWABeKcrY+z8JsrAc1dWfbinFXP+ycG4r/gCTJH5Ahph3YVTjFRqYw3fcnt/eZt3zonWaNvLjMt25Oje7jng==","shasum":"23d4ce5ad390bcdc0110ed885fa930682b630a10","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.1-6ae5eb7d.0.tgz","fileCount":42,"unpackedSize":45342,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICdT+uYe4kqyVJHr3ddVUPLpBiLpyIS/6hOOetxFYuMtAiByTiobyjBep0wZqQJV7R/Ss3VorDfQae5+GDtXflZamg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjW4TyACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqDeA/+JH9kRWARaSGhOidp1EB/aIdi0K6NSVlly6MK2MTEV9vvABBj\r\nH7g+l4IkyneDtLlYiqGgNsqQlt1UpR9gZTj6clKUSTOVbWG/Myk2uNfiUYeN\r\nFGbdLyyGpxoWnmVfDP+Jc24ooiZSWbZ4yWy+augZkx37o+cPm2BYxsCX9fR6\r\nsbgLlpVNFhKrJqamXNw4JSOsZ78DU1GrQx+SnzW6wUsAlgW9GqIWdaPiES2B\r\nrJy2MZq7nNeOHGELzPrUYX14M+7tAgpC7Y6GNUYbExDDPzhKwHd03cNhfrqR\r\nIQI6DH5DSpBapTI+dUoIsiSNprDx9Q3iVEKMrS32r2rRV+R2dXic+iv6RI7C\r\n7j2+CReGfRKhp8GdAnqr65KT3t66Uh8am5mlDXEylMM3H/Cwx/JyITnIoywV\r\nU9szWBgQAUWpYq22RM6r7p1Yh/24KUxR1WqNlBjUPbHUFfy+hAjcqayBXJJb\r\nr716nWzsYC91g63z0HIz+UHU70VoSxpqir0EiM0wVLHY7Iu9p4wFp/OvthSo\r\neINYLrcQB4z0mFuHsbGa1BW0+pqjmqYzSeKMM5/2kASFpZD9mlgzENGLTnoI\r\nusix2QZ8JfrO25poJ41embsQc7YLFFOggmKTOmdPbYvgZaBCVw8Dg5oVvEga\r\npnPYjmEDwxelr/z3+OrgzASkhXR/bj3pZ9g=\r\n=36Z5\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.1-6ae5eb7d.0_1666942194202_0.46441385994323636"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.1-6be59068.0":{"name":"ipfs-grpc-server","version":"0.11.1-6be59068.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^1.1.10","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.13.1-6be59068.0","ipfs-grpc-protocol":"^0.7.1-6be59068.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.0.11","ipfs-core":"^0.17.1-6be59068.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^14.0.0"},"gitHead":"81311d5fcc6a5512ed3414aa592bdc9e6c481b03","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.11.1-6be59068.0","_nodeVersion":"18.12.0","_npmVersion":"lerna/6.0.3/node@v18.12.0+x64 (linux)","dist":{"integrity":"sha512-PUzFUOvoDeiZsNeUIe1LJVNhRHevXmGSuKURWdpoP0mw8OcHAk2qVK8vEK3EUvCkdecmskZGCffjlojXNFVqPA==","shasum":"db81f4b7ed978120f7a7c3a4f49b84cf27b42d60","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.1-6be59068.0.tgz","fileCount":42,"unpackedSize":45338,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEA2c8PCjzcuGqwfEyDAE15FS6MrO1lntOSCD/PcBXCRAiBz53ZY0h6PcK/4gPrghVXDGZAi1dYG1V3ZEu3ChzV2Sw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjdo/vACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqn2xAAiiJTt+3HU3J9b5FQQRXfw+ZziV4CF5GMew5xDWI9gXP8RWyg\r\nrQyYuWql8crlGc65pkK+oTu7kbictGdfIq+YWwX75u0AhRMPKux4M+7hER7W\r\nXR291IAKLdM4sKcDZgAc/v2mcvalZaip4i9rEJgtIrQZzwBePckKlglATzqr\r\n/G8a7IYqfR4nKiv79OI8XPDi1HvZFjlEtj4gMhs9tlyKJzR55z+WeaarcXsu\r\n/OBZrx05sv+zpsuokztI+XCcWl7xwb9nNZSjA/IYiFZ7D9SSRmYjqIYcLie6\r\naCyFP0Qms1YCD3sUqfgvKO5elGvfEU//E2RKXWEAX0nmmtMrtUfzwMm2C9s0\r\nRepEQpZ/W5CgK2aISjV22qx7jNn9Aky1xhCsIhG28jJVqnT7WNKMlxleaxLy\r\nXvogrMrSZe74xp46p6IW0myGNFzHltrUgnDJIFnX1TYk4UwZsC3RKSNPtDa+\r\nszVDde/oyAA4LEschfoOgQ8iMeqNhtEIloVWaK0BFgwI7Z8znDhZPEs6C55Q\r\npZ2U6BSOkAMRZIjP4PCtUW044XGDZSNJDl0GmeL1Kuj+E92fCbGvM4DmcWyY\r\nbT5FYM3ImaDucPpM6cS6XmjNGBGqL6MZFLGNLJSEddUZToObAwInNvNopQp/\r\nlcPa3dtO2oT+0gO31flT/b0Nk1xuDnvhF5M=\r\n=QWoR\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.1-6be59068.0_1668714479208_0.2204778066214106"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.0.1-563806f1.0":{"name":"ipfs-grpc-server","version":"0.0.1-563806f1.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.0.1-563806f1.0","ipfs-grpc-protocol":"^0.0.1-563806f1.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.9.0","ipfs-core":"^0.0.1-563806f1.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"gitHead":"19b0474216e0a7dd7363dcd6733379790b68a1f4","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.0.1-563806f1.0","_nodeVersion":"18.12.1","_npmVersion":"lerna/6.4.0/node@v18.12.1+x64 (linux)","dist":{"integrity":"sha512-Wi7NprI8vbvumJpEERH+r7k2g1ZiOFTHPp6duBWfYiEo7mTxB5O6cpJloR74VwepmMgfCo4l3IrX/K3TuQ7dJw==","shasum":"42c2c3909067699066311ba291ea0436045a09bf","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.0.1-563806f1.0.tgz","fileCount":42,"unpackedSize":45333,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDPRvS45ZQFUSN7DHzTRVMCekvkpEBytOfT7QSYjBGHwAIhAO37JsZkDwOmEnBLxkqNODr2K0pRqJqJbf+z5N9m7sXi"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjvFjFACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoHLQ//Yp4gl3cjQTsSBIV1ODe+I14pK5YuUfxRD6TM5k30wg0uOYI+\r\n9zh/pTAEG+GSUgHCjSYTQ76dOomdYrKGzkB+smR69ufSJKji0TS3nmzfjd4d\r\nHuNmSgYm3u1cj7thxX98sjMAEFyFva73J3vavc+JaUoNN0exSth+B2C8+JI1\r\n9OTLT6LF2VC72pL1vQCvX/XXO11buBbttfXx/0W+zpsuYUQQbwDY+ojiAQEt\r\n0xpmHU8F5pc/VrUkAFWvdQxxnkf5jlFNQvqvrdLoZImalGg9rRKOO821MARu\r\nZjohSJicDusu8l6mOy7OlnoJje4SnQrmd3BGA5lE/RegeMmJxZxeldMiKvjt\r\nYTYJsiYlP7UkBsBEXVzVyGAhcHnfyx10kDJFES95Owz8GwbtUpzUPBeqkGv7\r\nwKP3zv5Eli61+rlku1K67oerGtgi6hZ1MqmUWi8nPNOMg5oeo22GKi2Sb9hG\r\ntD7DtKZekP4Qr/8qT3JG1EicHCOY10/8LU6k4hckoJ93eWNWHYPKnYrCkoO3\r\nYipVD5qfhykZCqGDJYPTWys6ooDyWOMuVa/Ndl7OGcI/USio2GMkZ5M8v8Vc\r\nrFNeEwWTKOc4PGGrpNBDwr1o1dyoG0CRZU2NiWo0elt4hvRhR5ycIL4sRzoR\r\nbeqX2/6/3WpFba7vg4GNRcvEJCorGyF3CGM=\r\n=PO3p\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.0.1-563806f1.0_1673287877095_0.23953779291715938"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.0.1-e85e5b6e.0":{"name":"ipfs-grpc-server","version":"0.0.1-e85e5b6e.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.0.1-e85e5b6e.0","ipfs-grpc-protocol":"^0.0.1-e85e5b6e.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.9.0","ipfs-core":"^0.0.1-e85e5b6e.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"gitHead":"5d268429a92d15e22b1cbf7fafadca662b131420","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.0.1-e85e5b6e.0","_nodeVersion":"18.12.1","_npmVersion":"lerna/6.4.0/node@v18.12.1+x64 (linux)","dist":{"integrity":"sha512-O64wlhs3wgBjYPoq+EaFTiOF9cqprmvef+1nLp61U28V7gCMENqNu/HKsJeHUTTR11LqhZAwXcUzbWLbQT1YBw==","shasum":"bb6885efd91e2ac75ce89fe1036d4578dfa724da","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.0.1-e85e5b6e.0.tgz","fileCount":42,"unpackedSize":45333,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkwgL4glY+ZXaDnZxCKCrblU2HKKS+VrQkV+c4ck5W8QIgTL/RphcG+jq8oKbln/ZdAZCXpKGO+f67dyXDGQbUzyA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjvGf5ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmolJw/9GrjcOoOKWbudB7NVY5IxEoi1xlY+8pP5sxd7k9np4I13c8Vs\r\nS/EVX6NVLsGKo4QxPQ/lv3iMVxFIad6F/qGHydGpjyWFLSvsPhai42op3MrO\r\nHIOltK1TD7hH+bYhUxrqq5eudFZJLcDqqmv6GqtKWWad8YiMu+LCAocsh8Qt\r\nhghQIbZkiRGS7o2HQv0s9h1XOaVHCUL+MRFDodVBMaX43hM8faOU4f8YY4ZJ\r\n6xOjrub2Uv2JBJZ8sBCuRjhGTrJ45LtUM3q8FjmogoLk5iwTFyipryolkcKp\r\n6li43dhW8bS/3srnwTVg2D0Mi/i6049Z+BzihDOjqpJBk5kwD+3SJqX+/DCp\r\nV2gnUxK+uDTXiakU7DTuFz7rWb/i+bO0UAtC4Ztk9DY8dBp2FuzHToX5prVB\r\n4F0XseLheh0bSO4Cjj/mb6uCZSQI87UeM8qoZFxODA6qlm0CSqXSXF6OG901\r\ntoeI+pPSv3UaEgODOrBJ7w7/AtNHgMjFFi1s+acOEOMwmX43LLMvyJfHfAkC\r\nq1QRiaA07Z7f6jqfWrHvha0yEwVU3J7crwidWJxNPxmdk3OFO5VAdz1zpx8z\r\nvQWtgk9igtMEg2I004cqKOcxwbBJvK79k1pvhoQF0Th6PiGngNqSY6mRVaTP\r\nx3RRPk15CFmVIyPzd1ONCr391SnS6yYpTUc=\r\n=pdAM\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.0.1-e85e5b6e.0_1673291769662_0.24538812655326492"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.0.1-2a6fede5.0":{"name":"ipfs-grpc-server","version":"0.0.1-2a6fede5.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.0.1-2a6fede5.0","ipfs-grpc-protocol":"^0.0.1-2a6fede5.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.9.0","ipfs-core":"^0.0.1-2a6fede5.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"gitHead":"12b210560953c0358e012a120d162b5f3f32d06c","readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","_id":"ipfs-grpc-server@0.0.1-2a6fede5.0","_nodeVersion":"18.12.1","_npmVersion":"lerna/6.4.0/node@v18.12.1+x64 (linux)","dist":{"integrity":"sha512-nGQ3WTOtIA7/45ogc726meGtzMnCVWutMjICZhN2W5Eyor2qDw5qn/k/tkTloAJROx/pb2vFr4Ga1nm5Wr5zUw==","shasum":"234613e91addec69ee70930b1097ab5fd89cecb7","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.0.1-2a6fede5.0.tgz","fileCount":42,"unpackedSize":45333,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDEAaSRoBxQKhZWuOJLhavdLfHpDDO5R7VtUW10MO+jcQIgYUswYANKieHdQlqR/4pXS6zBQ0E3Vj42gaisTnv6v6Y="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjvTF+ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoZeA/9GBDa+4FkQ9pVe8mr9BUwqufYWdCgFiuuP8BCu/bkZpDY12+A\r\naurLuM2BW00cyagCQYc+lZuDhhXOocBIzomzvmMzsy+V3MS6mf5LkpBzWvki\r\nQpBar7eMqoOfmtsUTB3IjtM49DTooGhPXPn3PHO+q7K12zAYlHEReDBWojqC\r\nyBxdw6PRhNU2GRmpLnFdbvRcEBpf17ke4Zj51HyS0rn+/S6YmpbflN7M1eH6\r\nd6uG+YlFOUFP0MQ47BdxDipZiIal6Y456FPJCHj7BM45LNqcFupcNHPSNkiV\r\nahBMK1mdYPsmti4CcU2BUkqgYt/QDGlw6m9ob9zLxDZEXN1faCk9SPAz5gL5\r\nGnbGZfnVh2jq3oLuA/fl+WbJ5aj7Q78mfXy07tMWfuGaMWVJl1jA1KcQKPKf\r\n2STR4RsHgmZDRqYQXTY0vKfYj3Yj0W8AMSpaUkasg4Q7+eZ1PK3oJK1l1vSE\r\nohep59Z8PaNK1sboNHW2uQr51tV7Dya34IaLtPkprL266ga3CcSeNETqaYt0\r\nTnhRAQ5qhj2u6DG6MioDtAQ/yLCE6kXvucdmpv0qV9ePkkkENDeFbuqoSRSj\r\ne8vxwCZ7SenicCZRnOL6DTw4+574mxZQfqI/6L0U+vRAi3CFrYTwDZ2I3jTc\r\nxqNwIhguqEx69yDDtt51dRz9RaGJipotrqg=\r\n=fwmp\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.0.1-2a6fede5.0_1673343358729_0.508507012195609"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.0-5f73ecad":{"name":"ipfs-grpc-server","version":"0.11.0-5f73ecad","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.13.0-5f73ecad","ipfs-grpc-protocol":"0.7.0-5f73ecad","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.17.0-5f73ecad","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"5f73ecadd7d397029be8dd9bc0dcd82469f07359","_id":"ipfs-grpc-server@0.11.0-5f73ecad","_nodeVersion":"18.12.1","_npmVersion":"8.19.3","dist":{"integrity":"sha512-xeYiwi5wcGZseBKX4QMzrkJgVlKl37kHuSjUfgtB+Q57j0jIstIy21DmlsjUWPwEb3Y0S7dxQYFH1s9JT0RYyw==","shasum":"4800edc0ce8cb54b2a48270cf5558330cda276a8","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.0-5f73ecad.tgz","fileCount":42,"unpackedSize":45269,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDPku/rOwFK/iPhIo++Xi60MLDGQqM4XZhPo+nAr773JAiAex0X6nEB1Zxb8SnAD1CUVo3P9Sk2JiJ/WhOEjysalew=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjvZ0QACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrkFRAApPgRpoQaXqqH9c3MVy/Sf/SOdCoYgydTxh/cDAOns4e0J1t3\r\nKT6Ppw8dwC+J0v50DhtWuJzXVGsFOgzNeYGV1bZLVwMioqMFoni99LfKFfwL\r\nxgLnQKvIKKSrHQYNtnn978GfoeUZjDlfOhpA8LoBPubDUyK0XKsXkJ6FNA4X\r\nhCJbaYHaju2zWlpq4hZ2sbI0cfq9vXt9Pp2FilzHY7VRspZkN/uvvTI87qGg\r\nhK11LKl2WmgGfgqh70fR80EYDaIWSCko/jETMCKvulwSJh1/zmv0o+3f4HfG\r\nhnJy8FYhHc+o+yxMbaPLxJjmqvI9eMYiT9eDxEICyZqG3uMzYf4HDjiBmjt+\r\nTGIr64+XJVtKia7QFRyA+USRny326NE3CsaCiBEhUHATupRboYqTSXjreGA2\r\ncN29LWCMAcvTAn6rPxzSDAzGX8dfOPXOfGhKm7M0bAqASN+5/YgzM0ZV29EV\r\njhzxhAeYGjvyrCfsE3LDsGveY7+KKUwWOPs3N3KlelSmUQGp4a00W4D9qQsB\r\ndlnCVZtbXlS4KTuSNJ1kq74sj6JpNDOehA3vhZ6kg53yQOAV01RteNvE0poO\r\nAu624SfDTR9CCriBi/X8uNCeClYWloo85gu6SaQAqb7XMTY6WEl3cVriLz8d\r\n+gOTTQ5psxXwFBO0JkiyEr89Lul70rEmg3w=\r\n=ps12\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.0-5f73ecad_1673370895893_0.0030124413776011494"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.0-4b4c124c":{"name":"ipfs-grpc-server","version":"0.11.0-4b4c124c","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.13.0-4b4c124c","ipfs-grpc-protocol":"0.7.0-4b4c124c","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.17.0-4b4c124c","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"4b4c124c4c49b1c60a68b4b8e24f1f00dd7f0517","_id":"ipfs-grpc-server@0.11.0-4b4c124c","_nodeVersion":"18.12.1","_npmVersion":"8.19.3","dist":{"integrity":"sha512-JAq8uNLzuWSRvcNpsIsoVKoy6QvdbZaLBULcayE54AId6S8MZhwiOUxr7XoNnAwMIXD7rAbgeJnhGfHaMgIh7g==","shasum":"413ef7153a8fd5e6b1a032f8e2a1b5a8471eae89","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.0-4b4c124c.tgz","fileCount":42,"unpackedSize":45269,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAvDjd6k1yg8ruBskScsYQPiLW14B+/b4xDFaIoArXABAiEAuQM+9bkyX7+0J+oBvLRLNZoKXy24FnB1DLNkRO0FFow="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjvt55ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpeeA//cVRlGb0Um24qs7mLL0dJYQ/ynBjx2JylWVnLwcMH8jpK4mEI\r\nFtuIQnF5vppAtuj+tu+12yqR5hTkAwhe5B1pt9X5kM/GQXRuiWdu3dFxMeNH\r\nNN623EclFYHN/NfgS1UQczEWOYs6aSjiyyrtu20Ohe/1F6FMfILwKAhEOA9v\r\npSpvwRBznlzRC2kxyJvabyR2wGNeAjV/P7WbtarLwWliI/73hCXib5aSVlKL\r\ni/eECLSzZO9veoZh6b1OzA9OXGvSWw/QfoiNyD5rPXSBGs4ibYAh+i7f9eCz\r\nZGL99NMae6vtLQUXbvsZD+BELMuaSS/5wzIQ+ICI+4K4t74FMScaPeGrgLEA\r\n+soqre5dADtFbmLLVRKxiNJMTpfbA65h/eLHkIZIa/kvPTvrz5jL9uP+tpcK\r\nG4pnIoe3Ta6SuFWBJArPIWiDAUBMbFocWNECkFbf0HmoOGxe4GB80ifZSVRP\r\nzaOk4q/rL4RTssLXtfKP5slnMd6/+CycXBTs55ZYtwjjzL6bO2S4caB8RNgU\r\n3pMf6QQQReN/9YIx6a6Nm1EN3zQzX2hrbFjetGSPxH7VuR5idxWkY+I2ydhF\r\ng+JghGZq/v0u23rJSWTfq4RASBD7wwH2p/MGmwPsc7Pb/OPNcEWW3MxpNl+8\r\nOF17qBn5jEndmcQIz08HGSLOs7LVL92N1J8=\r\n=wuKg\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.0-4b4c124c_1673453177510_0.09931377304413647"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.0-789ee585":{"name":"ipfs-grpc-server","version":"0.11.0-789ee585","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.13.0-789ee585","ipfs-grpc-protocol":"0.7.0-789ee585","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.17.0-789ee585","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"789ee58556083ef71a4ef44e3358f86c5be101fb","_id":"ipfs-grpc-server@0.11.0-789ee585","_nodeVersion":"18.12.1","_npmVersion":"8.19.3","dist":{"integrity":"sha512-0Px7SQsgbrDzBgE0bmcFxp75QCjwjueTjSu7SIzUcR1ttljg1/kO1J4MO9iTD1CQzSbRHabR2O9XcCJPNHn/xg==","shasum":"57b666e284a4634f14a8b79a4bd5b492c83dec37","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.0-789ee585.tgz","fileCount":42,"unpackedSize":45269,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGoKVDBBritqnLTiLAJhwarE0eKrW9tON1EsC+42IMnnAiBS4PpByd5zj7Hc3C2gIXvxnxn709Rw7dUADM40pIAqjA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjvuxxACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpZBA//RTQ09irW7DWzZks1GhPB+g0t3fjO+Boxse8vyUaZQHubCX1S\r\na3MMpqzfhbaHbd9zXfTU37fh+Y4QZBweTMIXdxxXvwjeVvQfs7iU5Zc3FWMk\r\nVBAL2sqBsMnGnRVym/+VxCEXjM3btqY32XzchYB6UvGhFE/WxNZjsDB2fOGC\r\n3Scuqe/Cu6Vb6GdNEXZiliuEwF4kidKiO1aE9ynyTYLGOulT6bIf2X6UTmjB\r\nJGKCw911lvyD7SkTm0iOi2r2ow8WWx28wKDRmS+Xf3A8BkGPYhWTk3CgjQ8u\r\npPQuIDx1eh5Xl9nR+1j4KQ9st4dZACbkXF2etvMpPnIqQ8XElHyi+vt4JM7u\r\nIxT0eYRoilP7+LmWTLlI7uwzh/FAR1r/GIwivRSL3f4ls0xfh+UPlF8yEg9L\r\n7/HgxGEKRMoRhiS/ZRf3dRq1qX5QdJMSFvB3vPPGISj+cW5g0kee2f7zuspa\r\n34r3H0IoPrPX7nWwMEb8ECfiBQjNJO4ohZo+n9ya/tClX4qJ06y9sWTPQXhR\r\ni/cikue+iNs4GkxxXQmyXiEYoKbEhqfSwyF7jv+eN0OurtH9nzyEyxR4Ucur\r\np3UbPuTVOKQFbhHwD+ojtCCzaYMpAJDELgta7YtIuVXeRwePwqeB8dOLR2ql\r\nwjqUWRUmyxeLdsRc9qWxElGWO70nCCp+EUA=\r\n=RBi1\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.0-789ee585_1673456753081_0.7190365221872441"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.0-fa578bac":{"name":"ipfs-grpc-server","version":"0.11.0-fa578bac","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.13.0-fa578bac","ipfs-grpc-protocol":"0.7.0-fa578bac","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.17.0-fa578bac","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"fa578bace93e459849a0ffcebbd6f222dc05652d","_id":"ipfs-grpc-server@0.11.0-fa578bac","_nodeVersion":"18.12.1","_npmVersion":"8.19.3","dist":{"integrity":"sha512-375U/2Io4728dlmb8Aba5V3oSXpiXudIKwpiUnHOTkXmY6eCOBGqOTNOUsmYVp+yqGU0c/kh4QotvmoAPONrOA==","shasum":"61232114a27ed539bdf48d0b8eac1d3863d01122","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.0-fa578bac.tgz","fileCount":42,"unpackedSize":45269,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHPT5OokSUuRa0Q7RZCgoHCnh9vFdyXZrtAnpjyX50osAiEArAU0mEbeL271ucB/6WxrQNkJmyFQX5r87/OBWK1Wh44="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjvvbwACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmruow/9FlybX7MJ8CMsBtQaMTI93Awgugd/ZBPq3o6VE5Ijn+9qzmKN\r\nyfua9+UouLkhSASofNhxBruRkB3I4leym2g5zSoE3MaxYwYV790qcuRHIC/+\r\niNnqAnM+upKQtRsObHLxs3nuxZWLgXJTh5l8U0N4l0XEMYq49MeaHzD8p43O\r\nRXYyklkzkmPwsFisMx+BGdCBYgHccj6n6bm6WOqxQGLZGcBjuWcTwP+kFZRy\r\nzD126tx3gEjblKqRGrb4nA5duaLDsV8yxCGf+4BmIGHOpbwPsn85puCCa5XW\r\nwc4HXSh5wEVKuDmT9IWOEkIUi29zexu8fGjnGUrGJC53+5DqlzEtZimq/zlB\r\neO+7jcoF5LEdWchyY4/qaXJCboaklNsD3PAhqa73O/Sq5wOW+VZ8j6QQ2z9Q\r\nQXrXByz4M5se6oxc4UATQa+43Xvl8tpWe2fnqx4NtGGKNEpWg+UVqTdJvk+7\r\nK28Tu72ZBCV8FtcUlGAO/IjsVkcDPUzLz3TEowbOILZpSxCNYDJTOuelLaTp\r\narc4ZJnK4LG0R81dXYFvXqiVC7BunQvyRfn80MRRXUcLC1I39gIqHU3NkvUi\r\nXvP9Pyu/EvJxplla5tE4Lx9/rA+jbeyEPnDtI5mjym5uLqSZi5rJXHWnpzMc\r\nQpLtJNEe7cZ6nLC4QoNMmM+X/U+b6s1ttsQ=\r\n=z06w\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.0-fa578bac_1673459439747_0.4094710046752117"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.11.0-d1c3abb3":{"name":"ipfs-grpc-server","version":"0.11.0-d1c3abb3","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.13.0-d1c3abb3","ipfs-grpc-protocol":"0.7.0-d1c3abb3","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.17.0-d1c3abb3","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"d1c3abb32b57379b5446d5eda232d7750a2ecff0","_id":"ipfs-grpc-server@0.11.0-d1c3abb3","_nodeVersion":"18.12.1","_npmVersion":"8.19.3","dist":{"integrity":"sha512-V/hUejD7kACgbCg/CDzuUe8wO1sf8IkHCIWV8ZLQEZPj4gYnJzncwCugDBzsF4jI5PZn6aeceWQfE8XhpXC1mw==","shasum":"b788c4c7f12378ebbd1f8a86800d9dcc6fb8d5b1","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.11.0-d1c3abb3.tgz","fileCount":42,"unpackedSize":45269,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC6wlvl1Pu8ytnO8GmJ1wcrSHx9Jypn51jVX33zubuf2AiAOfAnMQRQmYqLA8sIG7Ae7breLtrP2YLu7rxNFC7KZzA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjvvtMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoJog//a94j/HPsvFi6ihpRSp8OUre2E1MuYA65jwQnn+KV0CofFW+5\r\nKXmR8SgGS3vhOoFZdSMQ+xsf0ULlIL79QJQyVGWIQfPQUxEnNKuFD6qiD1+o\r\nmIVQ1H/VUbOh1BpKmGXGA8PlFfNu8KVu2Ti1DzBLc7PyHHzM7vK//sIBDCc+\r\nk58BfZZotinIaq06evoD6wiFCccSuOXkrGP0o1/bemmUVUNpu19Iz3EqA6TF\r\nTiQU+hbPQC9dIRdfCNleIVS2TLz0BK5Z2bvCw0Oo9c89Nwent2GAGq0pFXFv\r\n1PwC3o2HcDTJnp6xyDiZ1g2rSimB98kDULFkxJNcyvH2Qnc/qVBTTtOXsd1C\r\nmlHLsUwI6QkHHHgRf4aj/7TOfcuIaPKLTgM2VOH6TA54s/DfvscFBP9x2IGP\r\ncSW5JBHrMVgxh7RvnXWE9XR+8SFL3V5HDqon1zqG9eqKsFMMhfBB2jNIRMur\r\nZ+ZtKpmVdQNgnN5RuAg5+yIwzot+LbwbnzkuVK3zFhaJ5VeMYk8rkRLEEStG\r\n2gkplteE+KsQMo//geOWjBQLkaCJBVszpA9joxGJroCJf1BobB9HqzP+QCe/\r\nraqy0mgCyZ9yERxLfETdttHvO5XljYhBTjJncfaGR/6sFRjdMeoihM1DFgxg\r\nN3D2DVV43wqSd7bYXkLoqGbi5fqI3YlwU6I=\r\n=J6MO\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.11.0-d1c3abb3_1673460555811_0.3903709670124398"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.0":{"name":"ipfs-grpc-server","version":"0.12.0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.14.0","ipfs-grpc-protocol":"^0.8.0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"^0.18.0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"gitHead":"6e940670681859682d41ca1339744955c9ee20bf","_id":"ipfs-grpc-server@0.12.0","_nodeVersion":"18.13.0","_npmVersion":"8.19.3","dist":{"integrity":"sha512-fF9hjg/JK26oIGrqVQ2IBzZZ8ll3AptrMNg3UBDbKX4UTVeJMVGpE6xrfVTzYSUsnUOttFgtdHw/6D093YbqvA==","shasum":"d407cbd36b0bb896f6d48c8c78cc2cb086bbcb53","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.0.tgz","fileCount":42,"unpackedSize":45236,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAFZporurqnCYK1NJMhvcDLAqdJml59vMu424y5PHyEHAiEAvUYypovalG3mecE2Bcf/V8zgbifg9MDWe566Vv0chL4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjv/DfACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqDgQ//UfTlS7yBOosii+EvjtwFb9nSAvhjgo5uw8Z48rk9ijbIRMNu\r\n7/jMkvz/KpdYtS+n/uaonUQl1CLAnI0DAnSRVmnfbvX8gwsmeohtn78P9Qo+\r\nU+ko0fqUf0PF9JCgYdl9VSSr4teE6DiJpivD2w5vFcaUp/6acJ5HGYLJzsiU\r\noiRdcqFx6g1ikvnjDCVP0jyaFVt57IaOZm2g3KCdpLrsob9kpvTXnU6VwCos\r\nMr6tAY831Nd2tIIxkfqZpk9fRGj3kAa4Pw5sRk5cFJod4+h+GFGW9eNrzAQ7\r\nIrCe7OlGRyMeREH6gzrGcPBYy9NNDZ+fz/WD0gCJ6hbc7dL/rNUzxqSBo9/r\r\nfJpTaP9PirOL6Ypf6d1u9R7h8wKJE+jsDZbqaMrenaqDvfp7PpahKU7zwqPQ\r\nXMmNmMgjlm9GP+UNRJWXdDUsVqHuCtOLjgt9imQlYfQg5wmJQa0/UBV3HO6V\r\n3g+zRvacs9tYsis69Uv70AxFsh/L4+xYSk8YynwEcSmjfUrKJnMLi2eNnWWN\r\n5bc5X5fT6mfRwHyL4nzRkWvO3EVfhRSl3O68wmXDxXSxGadYCxv1TFVHqnzu\r\n/FAvdt4MK16/uM6QDWuNrXf3S+VeEkgsx0RX9FB7FG4c4D03XqpTUmek38/F\r\nrynrNDtYtlp/lOF1uHHdqWzFRWOqUmc/IwY=\r\n=FlO3\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.0_1673523423657_0.8370908449653587"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.0-6eeb1be5":{"name":"ipfs-grpc-server","version":"0.12.0-6eeb1be5","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.0","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.0.0","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.14.0-6eeb1be5","ipfs-grpc-protocol":"0.8.0-6eeb1be5","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.18.0-6eeb1be5","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io)\n[![IRC](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)\n[![Discord](https://img.shields.io/discord/806902334369824788?style=flat-square)](https://discord.gg/ipfs)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/workflow/status/ipfs/js-ipfs/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"6eeb1be57c8366b82351030e49a5886d1aff8bf6","_id":"ipfs-grpc-server@0.12.0-6eeb1be5","_nodeVersion":"18.13.0","_npmVersion":"8.19.3","dist":{"integrity":"sha512-Yv20q7LeuvT8X0Us86GsoBnXmJ8qs85a5qizT5NIRnGejoVw3cz2K70Xd5VvZGfrfDWeN7eT6W0KJjTfnhbTXg==","shasum":"e9736e98e7724bbd704e05edbac3193d2f5f9a31","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.0-6eeb1be5.tgz","fileCount":42,"unpackedSize":45269,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGdKVLq2Z0EJyHgV3PzXGaoRtnHW0MIqK4bfBhQ5K+H3AiEApaw39Qt7uuCy7yN2iX6QXEWM2H4xX+r1SZYckohNAyU="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjwaENACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr7ug/+IdVTzqTTDNIbspofeZW4tIFDv9h+xrbZqXGpQ+1ESh3K3fb5\r\naAzS0ayuftq0j1WM4MwIlFhRafmWQuhZKT6z9yZ64r8tnXHd7aFNwsszhHdG\r\n21WDIvXGcoBeGMi5uHz7T2NsAikhIldjq0J4/u1+XLF9UI/FQk/TvEYzaIY1\r\nFcH1Rf7NspemvF/2uzWPOJLSF/NUHZJi4ipsu0IYXUD6mvvhbxxkEEl/wH4A\r\nI2MOtxGwVF49BmpJnpVDrBEbawFUIZz6gIZ5qt0rlSsYn3WDM01qwqc4Uk3V\r\nZqKXHbPD8mVeJhjtaOeYhOlqwWtwE1xrtYGr5ZpVeTqY7LfskmOtAo5BUiCZ\r\naeOEBt6WiYaa05DsqP5lkRNWele/fDBCuJu9vK+1WsFazRgLkY6dIVxhkozC\r\n6VaY4ZmjugUikNSeLKPMs5buQkg5zlDV1MfQ58RO3r2HeskKsMLUs9X6kdHs\r\nN4rN28edjNtu3fHPV6UIXmhXBfh9HWq6ogxDPsx4klUNsekrFuZpLbcUAaIA\r\nirSXlyRihPVX9LfbcKaRJA9smar/U6nrqdVhASJBh5VE8bgoJH39ZuVLWo0q\r\nJRHQnZHVFdblyOOJt+QynuvJ95GxQPJ4H1s3uwN2v3uRMUdTuVe5AcVg/j7j\r\nL4mNS68XYNtbBe9SKolquuSIdTzRvqHtfZ8=\r\n=Fdch\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.0-6eeb1be5_1673634061267_0.8869553806815491"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.0-ab02e8f8":{"name":"ipfs-grpc-server","version":"0.12.0-ab02e8f8","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.5","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.1.5","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.14.0-ab02e8f8","ipfs-grpc-protocol":"0.8.0-ab02e8f8","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.18.0-ab02e8f8","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech)\n[![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/js-ipfs/js-test-and-release.yml?branch=master\\&style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/js-test-and-release.yml?query=branch%3Amaster)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"ab02e8f8b3cf8f4eeb9991fef3b0104728ced675","_id":"ipfs-grpc-server@0.12.0-ab02e8f8","_nodeVersion":"18.13.0","_npmVersion":"8.19.3","dist":{"integrity":"sha512-U4tT4IJ8dbJSqjnOu5CzcUjaaPat7CFlYOvVkGsQRE4cFoxfPn7S0AshLFCDqEzVuy67KtAdqaRAp4+3qlwF+Q==","shasum":"46bc380b852e1752f1c4016106900f7cc994e360","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.0-ab02e8f8.tgz","fileCount":42,"unpackedSize":45198,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCsdLXQpHkWRknwYUcwY3PflvmnQ6PLPvhfhopntpkO/AIhAOcragG9+ETt1R0KrEz0nsUblER78SqYUsoO+sqxU0VU"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjxpOJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmovrw//U/AgT3nTdT/D/m5VZ1WeYOOzoJigQKavGsAQNb/ywaoHzC1B\r\nCfUN2Vyi5J/L0Hy1EHBYiN21WhXUcrGUH7u6W8jmsdSj6kq3u5t40Sm713Za\r\nAhQ9QML328xFYVMzCUUsWhhHa7eOZV/D2zkQhsgzpVFTh6dlD+Ze+boDU0O6\r\nUgBttXmVT4lWCWfkQXjhaCrZ2HLtx6guhU3pgUEOKlKphuWPQrBxJRQcEdvC\r\nkLdGVrkxYbnvcadl9FXsxpRd7QHz1zM3XraKjdIS4Dr8B7gPbqiuBaiaxBxW\r\ntqmJ24XZQGTxBwncCGVMA7/nYp1XJCITrS1UtSGhVW6ZguJLEm/IKT5gSrMn\r\nwNR5iPjfSYBNLc6FDk3tSGI7i1UzcwoHeWZYVkp2Nf/Z8NbT7My82dulRaG2\r\ni2ghNhLa5s8Xut8C3d5CjI2LS0kcg9zEt673s4itG6yABddgclrv8ZdqWjn7\r\nwiz/lqYFz7r9ioHRAEHdMfeWpXKRGnpnm73wSMM6yuK4vV5ihA+fHRRbOG2s\r\nHwhzU3BsK36q0u2L9fW9Mnz+qgyAR+NOBhsmm2BN78dHtVB/4OPFILPPAGyv\r\n8ySLpUV+bkIzChV/0UG5TIVflWijPINaAePdZs0WEquvM3Ngg0BGYT7VBTDx\r\n0TrHxnOSMr3iHpnOvAfaDtYHCW02S+Fm20Q=\r\n=Xnsh\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.0-ab02e8f8_1673958280871_0.04670133505297902"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.0-3bcabe38":{"name":"ipfs-grpc-server","version":"0.12.0-3bcabe38","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.5","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.1.5","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.14.0-3bcabe38","ipfs-grpc-protocol":"0.8.0-3bcabe38","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.18.0-3bcabe38","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech)\n[![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/js-ipfs/test.yml?branch=master\\&style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/test.yml?query=branch%3Amaster)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"3bcabe3818ce8bbbafe0cbb68749b286d8a7edd9","_id":"ipfs-grpc-server@0.12.0-3bcabe38","_nodeVersion":"18.13.0","_npmVersion":"8.19.3","dist":{"integrity":"sha512-OZM73u/C7fLc46H03+yxAN8kdcpcqUrBz0yXiydB5rnx7Fx/YNDcCil/G14yl4P5KJZHJaKjok3w3P6TMHPPDQ==","shasum":"49890c6453e770449df0c7a6a38ca7d219c671dd","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.0-3bcabe38.tgz","fileCount":42,"unpackedSize":45168,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC5OUF35m9y5ZpNRBUetj7+RE870mf0qRwu2K8WJD2eiwIgbch2vKaxoamrg0+dh/mB8fhUiBffS8A8D66o57Ggr1M="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjxr9wACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpeKQ//XRP8fyQzHqfwfemzcs9GpnEqfMIwR/aVFjT9zlLGhq0LLJYb\r\nbW4QHNP3GeJzz3LUH5OGhasD9O5ANlrtaX5951exGftqu30vkD9BdJ87KHU/\r\nmaf1OG2X+peo/pfkeMp+JI48MeLJxH+f9Gt6R7a7l4qgMNwlOyGl3iENYKG1\r\nNzRriU5P134x0JbfpKDq3ZHLWObw1p1XCrHdWWFm+VB5tyXCxgAXHk//XXqN\r\nprAdnP1gdyw8fnpy5ltCO3L2D2oSzFJdDVkE0XBZY+kJLqVg7cee+PRpv5OW\r\nnoI8N1jCRcRYG8g/LlbWz6ACpwruD9W0J6uMQUvdkdlX4LltAQAUQxyVcpeq\r\nC0EbzGtTgKjICrXXBflQD8rVW0tDHV7HZpkF2frMTN4LIQu7stONIricIHcW\r\nf9CWfRrYAEPEjGG6RNkGjAQXa3omRmOYmHPAHi0hVFHqqPgQTICVAOmM98uE\r\noQykW+8Imh+Anx4665NhEkkjYldOBKecV7SfAvFktjOB+F8SgL/vbEfx7xQQ\r\nnhIPuMV3BXdkPikam6BYhiJwOB9Sp+wPFxmn+HbmOnnpps4RS6CkEr2Itzfl\r\nv9d6qTYTxMPyitM8J0wrztzS2ViLCvwHZp8ZN3y+QUAOjhXi5HQQRccOztpZ\r\nCpjdZ+7Hc6GtntWfKUpl5p20zP6SOQim5c4=\r\n=swkN\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.0-3bcabe38_1673969520420_0.7954589170801936"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.0-b64d4af0":{"name":"ipfs-grpc-server","version":"0.12.0-b64d4af0","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.5","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.1.5","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.14.0-b64d4af0","ipfs-grpc-protocol":"0.8.0-b64d4af0","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.18.0-b64d4af0","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech)\n[![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/js-ipfs/test.yml?branch=master\\&style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/test.yml?query=branch%3Amaster)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"b64d4af034f27aa7204e57e6a79f95461095502c","_id":"ipfs-grpc-server@0.12.0-b64d4af0","_nodeVersion":"18.13.0","_npmVersion":"8.19.3","dist":{"integrity":"sha512-GrrUOAr4IkFfyczIU3UU5OYrkyJLWgqe7TUlzD+6fU9ER7+mQs3EhWKkTOrCbXUIT2oUzrp7mNKbbC0UIPGM8Q==","shasum":"076e3c4a3708691e0dbc69ae94e157ab4d00e8fe","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.0-b64d4af0.tgz","fileCount":42,"unpackedSize":45168,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQClZTIoNL6mN5aRIahRva88WHNW6MJIkGcXHFtQmp0XZQIgbggRUvtn/NOgSSXjVY8BLJJ2c6aMs4RKi9FVaWSB5Lk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj2kv+ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpdEQ/+P6BKvgiCvBvI00p98HuNTd6xbwtGYsa0Eul0RRkpit9cp/Q1\r\nk4wv2/3GAbPum4pXmXdmJj1uSgpFTfk76aS1efDHrXpd+FJV9TB0TAxqBb5S\r\nDRS1WrzqVKhyLMnd/KjjMGAlAPVTfdaiKAsREjs3ODtUvixFtw1vx0SLjXfz\r\nzHY1mqM1Johq447Mbp9nSBIU4/ONzRBA7ENhR0CDUvzeGmlQUwIIVukC4jEw\r\nuqHQZxFkEEGpmVaeDoK6jTXl7+Jc5eZn6yCAHl8rI2HKWO/WMLWLXl6pBhN+\r\nn5rYwqnfDhh0tqSbilQD9O2+Lp3eilycSeDAQM3w3tVJOHWsOvPB/vVDc3kV\r\nJ/Jw1mFnWgZ6Qq9XOHc0DpuJe/tmxbe5FkdlKge3s7MGRshLymVttzF6w4Z5\r\nSIqE47h5GwkfrL+D7fk9QDo/2c9pK+yXZ5mui1TWBwCmyowtIXh7+DYL6lRH\r\n1PLrv8YyfqqCVZaMnUusbFFXH0Ajy79Q4jvktsyx1TZrSEbMrDNENWsIVmHh\r\n7gBt6yz4BCMTAVUxVLx4c1s9JJRjkrq0u3apC/PO6T+autn5D6kJgkNDe6Tz\r\nHPoRpzN0FjgoPkX2GxHSJ7tmfq47gJeyEwHcDkQwyKKEIAK/YOAStEvbV+On\r\ne/evg1K57PPUDD0DonT/9wdYRuVx1aeKW1E=\r\n=8k3/\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.0-b64d4af0_1675250686212_0.6203924075540275"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.0-e64813f6":{"name":"ipfs-grpc-server","version":"0.12.0-e64813f6","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.5","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.1.5","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.14.0-e64813f6","ipfs-grpc-protocol":"0.8.0-e64813f6","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.18.0-e64813f6","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"> # ⛔️ DEPRECATED: [js-IPFS](https://github.com/ipfs/js-ipfs) has been superseded by [Helia](https://github.com/ipfs/helia)\n>\n> 📚 [Learn more about this deprecation](https://github.com/ipfs/js-ipfs/issues/4336) or [how to migrate](https://github.com/ipfs/helia/wiki/Migrating-from-js-IPFS)\n>\n> ⚠️ If you continue using this repo, please note that security fixes will not be provided\n\n# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech)\n[![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/js-ipfs/test.yml?branch=master\\&style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/test.yml?query=branch%3Amaster)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"e64813f6fdc681328da7cb893c93e1f4f70bfc99","_id":"ipfs-grpc-server@0.12.0-e64813f6","_nodeVersion":"18.16.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-EhQK6Pu6VQmCaxKn79gZqQhgHEbdUTVNla6uOFGxgd1tFhb0fqNr5yjsx9/7+3xEvMauEJ1lSZvpkuOBTmv+wA==","shasum":"0f89ad3e4f115402bc936816ee738b8b0afdc5ba","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.0-e64813f6.tgz","fileCount":42,"unpackedSize":45638,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG8KZDtOPTtP5Tx/FcbIrg/vvfurWayVpLFNsDcp90+0AiEA/82D6S0GTXL/F0RZCnedONojpIn00AUoV528JNYcvaQ="}]},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.0-e64813f6_1684953966377_0.2945616187882849"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.0-4694e806":{"name":"ipfs-grpc-server","version":"0.12.0-4694e806","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.5","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.1.5","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.14.0-4694e806","ipfs-grpc-protocol":"0.8.0-4694e806","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.18.0-4694e806","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"> # ⛔️ DEPRECATED: [js-IPFS](https://github.com/ipfs/js-ipfs) has been superseded by [Helia](https://github.com/ipfs/helia)\n>\n> 📚 [Learn more about this deprecation](https://github.com/ipfs/js-ipfs/issues/4336) or [how to migrate](https://github.com/ipfs/helia/wiki/Migrating-from-js-IPFS)\n>\n> ⚠️ If you continue using this repo, please note that security fixes will not be provided\n\n# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech)\n[![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/js-ipfs/test.yml?branch=master\\&style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/test.yml?query=branch%3Amaster)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"4694e806aea15c66db32e3b4be81c0a5e2fb8ade","_id":"ipfs-grpc-server@0.12.0-4694e806","_nodeVersion":"18.16.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-OoUR8k0Yfm2bpn3h+0bOFH0r2afAeYvbi4+9CRU8weomosLRPkXoaZytxnWOOCbIYebRuSaaiQ4E2azpNQOrBw==","shasum":"92a430d54238d8474cc3eaa4696f2d04a01b84a9","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.0-4694e806.tgz","fileCount":42,"unpackedSize":45638,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBM3JUH6pK7bHLPsjTsc/CLbpNazh3wnb/mskSp6qob2AiEA4mzrwVKQ9DFVrGIeAc99uzFPq9ld9pIIRrm9sTyTo0Q="}]},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.0-4694e806_1685014324289_0.38379065812474145"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.0-6d95ce08":{"name":"ipfs-grpc-server","version":"0.12.0-6d95ce08","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.5","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.1.5","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.14.0-6d95ce08","ipfs-grpc-protocol":"0.8.0-6d95ce08","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.18.0-6d95ce08","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"> # ⛔️ DEPRECATED: [js-IPFS](https://github.com/ipfs/js-ipfs) has been superseded by [Helia](https://github.com/ipfs/helia)\n>\n> 📚 [Learn more about this deprecation](https://github.com/ipfs/js-ipfs/issues/4336) or [how to migrate](https://github.com/ipfs/helia/wiki/Migrating-from-js-IPFS)\n>\n> ⚠️ If you continue using this repo, please note that security fixes will not be provided\n\n# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech)\n[![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/js-ipfs/test.yml?branch=master\\&style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/test.yml?query=branch%3Amaster)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"6d95ce0864055e5236ac88c0999460ebc5075c10","_id":"ipfs-grpc-server@0.12.0-6d95ce08","_nodeVersion":"18.16.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-O98QT6zMhtDtW1SnMGg/ttqvi+ws7OUsG095nSGTnVfzT/XpfvZ3u6zsSr5ChGttwFY8/VfMCvh1QSWQLrUpWQ==","shasum":"41107086427f9ab2aa1ee23f74d93cef568cac6f","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.0-6d95ce08.tgz","fileCount":42,"unpackedSize":45638,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDwGRS5h98q1EHBqqtR8Nr6yipc/dzcEjX936Fpzj3cdgIgNznECrLp/nf2EDmrvZlHU2Xxt2YjvBiuQ/nyNcex/ew="}]},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.0-6d95ce08_1685016657519_0.8199255100659528"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.0-7b79c1b8":{"name":"ipfs-grpc-server","version":"0.12.0-7b79c1b8","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.5","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.1.5","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"0.14.0-7b79c1b8","ipfs-grpc-protocol":"0.8.0-7b79c1b8","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"0.18.0-7b79c1b8","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"readme":"> # ⛔️ DEPRECATED: [js-IPFS](https://github.com/ipfs/js-ipfs) has been superseded by [Helia](https://github.com/ipfs/helia)\n>\n> 📚 [Learn more about this deprecation](https://github.com/ipfs/js-ipfs/issues/4336) or [how to migrate](https://github.com/ipfs/helia/wiki/Migrating-from-js-IPFS)\n>\n> ⚠️ If you continue using this repo, please note that security fixes will not be provided\n\n# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech)\n[![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/js-ipfs/test.yml?branch=master\\&style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/test.yml?query=branch%3Amaster)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","gitHead":"7b79c1b8df5c818dc124b346ea28330455732d5c","_id":"ipfs-grpc-server@0.12.0-7b79c1b8","_nodeVersion":"18.16.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-lg8R0+jOYr0Sal0wcKG+jLej3rfF0CC1QogRuQpU8aL6tPbKZj+yj3ybVoCqio+LD4NP7vh1nxxPz/u73Xe+0A==","shasum":"4f005b0b427676c0aaffc221aa588e2c5c2745b6","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.0-7b79c1b8.tgz","fileCount":42,"unpackedSize":45638,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDToissRl8J6aHsOLKt8/7dwtPq99+8gotLARQTJQJ2nQIgGCUa0gBUqeiZs9pUqGEjg2bXzKj+QjbS42VJD8kYoqs="}]},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.0-7b79c1b8_1685018800038_0.7923027798218591"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"},"0.12.1":{"name":"ipfs-grpc-server","version":"0.12.1","description":"A server library for the IPFS gRPC API","license":"Apache-2.0 OR MIT","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"},"keywords":["ipfs"],"engines":{"node":">=16.0.0","npm":">=7.0.0"},"type":"module","types":"./dist/src/index.d.ts","typesVersions":{"*":{"*":["*","dist/*","dist/src/*","dist/src/*/index"],"src/*":["*","dist/*","dist/src/*","dist/src/*/index"]}},"exports":{".":{"types":"./dist/src/index.d.ts","import":"./src/index.js"}},"eslintConfig":{"extends":"ipfs","parserOptions":{"sourceType":"module"}},"scripts":{"lint":"aegir lint","test":"aegir test -t node","test:node":"aegir test -t node --cov","clean":"aegir clean","dep-check":"aegir dep-check -i ipfs-grpc-protocol -i aegir -i ipfs-core -i ipfs-core-types","build":"aegir build --no-bundle"},"dependencies":{"@grpc/grpc-js":"^1.1.8","@libp2p/logger":"^2.0.5","@libp2p/peer-id":"^2.0.0","@multiformats/multiaddr":"^11.1.5","change-case":"^4.1.1","coercer":"^1.1.2","ipfs-core-types":"^0.14.1","ipfs-grpc-protocol":"^0.8.1","it-first":"^2.0.0","it-map":"^2.0.0","it-peekable":"^2.0.0","it-pipe":"^2.0.3","it-pushable":"^3.0.0","nanoid":"^4.0.0","protobufjs":"^7.0.0","uint8arrays":"^4.0.2","ws":"^8.5.0"},"devDependencies":{"@types/ws":"^8.5.3","aegir":"^37.11.0","ipfs-core":"^0.18.1","it-all":"^2.0.0","it-drain":"^2.0.0","sinon":"^15.0.1"},"gitHead":"bf1bc8b18d750d5591bdd575a6d0f4c067d61d0a","_id":"ipfs-grpc-server@0.12.1","_nodeVersion":"18.16.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-FIRV3RVcRqxGwLSyMZFarqYmBtVyLkhmYhHLnYBdHc3Z+D2a7KUUNOi88/UcF7jA0xXKpK7l3JG2voBJyXkYGw==","shasum":"1ecd235dca30763004502f7b771e07170ace24eb","tarball":"https://registry.npmjs.org/ipfs-grpc-server/-/ipfs-grpc-server-0.12.1.tgz","fileCount":42,"unpackedSize":45605,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDsdMGCiT4cAN948B4iWLKpOMxSaozmudCFyv/2tMMcrgIgUUrdiojACKUdkKK6b15JYkg3Cj44VsL4Wly6Y297kKk="}]},"_npmUser":{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"},"directories":{},"maintainers":[{"name":"achingbrain","email":"alex@achingbrain.net"},{"name":"ipfs-npm-publisher-bot","email":"alex.potsides+ipfs-npm-publisher-bot@protocol.ai"},{"name":"npm-service-account-ipfs","email":"npm-service-account+ipfs@protocol.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ipfs-grpc-server_0.12.1_1685026803075_0.47723654446858976"},"_hasShrinkwrap":false,"deprecated":"js-IPFS has been deprecated in favour of Helia - please see https://github.com/ipfs/js-ipfs/issues/4336 for details"}},"time":{"created":"2020-11-02T11:34:12.785Z","0.0.0":"2020-11-02T11:34:12.876Z","modified":"2023-05-26T10:44:43.679Z","0.0.1-rc.5957":"2020-12-18T17:46:52.634Z","0.0.1-rc.5958":"2021-01-13T12:26:11.378Z","0.0.1-rc.5959":"2021-01-15T08:51:14.983Z","0.1.0":"2021-01-15T11:42:42.476Z","0.1.1":"2021-01-20T07:49:36.656Z","0.1.2":"2021-01-22T12:04:03.907Z","0.1.3-rc.3":"2021-01-30T08:09:04.462Z","0.2.0":"2021-02-01T11:36:38.829Z","0.2.1":"2021-02-02T09:06:36.188Z","0.2.2":"2021-02-08T15:33:58.232Z","0.2.3-rc.4":"2021-02-21T09:16:17.299Z","0.2.3-rc.5":"2021-02-22T16:41:58.986Z","0.2.3":"2021-03-09T10:47:19.321Z","0.2.4":"2021-03-10T11:13:08.912Z","0.2.5-rc.3":"2021-03-31T15:16:13.179Z","0.2.5-rc.11":"2021-04-28T12:16:23.424Z","0.2.5-rc.14":"2021-04-28T17:12:59.470Z","0.2.5-rc.17":"2021-04-29T16:56:36.273Z","0.2.5-rc.18":"2021-04-30T09:24:36.004Z","0.2.5-rc.19":"2021-04-30T17:04:54.523Z","0.2.5-rc.20":"2021-05-01T17:52:55.313Z","0.2.5-rc.21":"2021-05-02T09:00:36.928Z","0.2.5-rc.22":"2021-05-04T07:45:10.344Z","0.2.5-rc.24":"2021-05-04T10:56:58.642Z","0.2.5-rc.25":"2021-05-04T11:19:17.055Z","0.2.5-rc.26":"2021-05-04T13:55:51.554Z","0.2.5-rc.27":"2021-05-06T11:43:04.144Z","0.2.5-rc.28":"2021-05-06T14:17:58.026Z","0.2.5-rc.29":"2021-05-07T11:59:14.856Z","0.2.5-rc.30":"2021-05-07T13:39:47.356Z","0.2.5":"2021-05-07T15:45:35.855Z","0.2.5-rc.31":"2021-05-10T11:57:46.911Z","0.2.5-rc.32":"2021-05-10T12:21:10.785Z","0.3.0":"2021-05-10T14:52:54.224Z","0.3.1-rc.1":"2021-05-11T06:09:47.523Z","0.3.1":"2021-05-11T18:22:10.594Z","0.3.2-rc.1":"2021-05-11T20:27:22.298Z","0.3.2-rc.2":"2021-05-13T18:06:53.393Z","0.3.2-rc.3":"2021-05-25T14:40:21.837Z","0.3.2-rc.7":"2021-05-25T16:06:27.069Z","0.3.2":"2021-05-26T09:32:53.044Z","0.3.3-rc.1":"2021-05-26T12:25:05.640Z","0.3.3-rc.3":"2021-06-01T20:39:21.268Z","0.3.3-rc.4":"2021-06-05T06:17:24.539Z","0.3.3":"2021-06-05T06:32:45.933Z","0.3.4-rc.1":"2021-06-10T09:26:45.395Z","0.3.4-rc.2":"2021-06-15T16:49:08.386Z","0.3.4-rc.3":"2021-06-18T08:11:28.572Z","0.3.4-rc.4":"2021-06-18T09:21:07.084Z","0.3.4":"2021-06-18T11:15:51.994Z","0.3.5-rc.1":"2021-06-18T15:58:07.105Z","0.3.5-rc.2":"2021-06-25T15:13:55.959Z","0.3.5-rc.3":"2021-07-01T16:05:49.099Z","0.3.5-rc.6":"2021-07-19T15:31:35.418Z","0.3.5-rc.8":"2021-07-27T09:29:01.722Z","0.3.5-rc.9":"2021-07-27T10:01:21.716Z","0.3.5-rc.11":"2021-07-27T10:39:04.749Z","0.3.5-rc.14":"2021-07-27T12:20:15.785Z","0.3.5-rc.17":"2021-07-27T14:23:49.939Z","0.4.0":"2021-07-27T15:07:52.611Z","0.4.1-rc.1":"2021-07-28T11:30:13.411Z","0.4.1-rc.2":"2021-07-28T12:25:33.411Z","0.4.1-rc.5":"2021-07-28T16:56:45.681Z","0.4.1":"2021-07-30T17:08:26.772Z","0.4.1-rc.7":"2021-07-30T17:30:59.742Z","0.4.2-rc.1":"2021-07-30T18:57:21.293Z","0.4.2-rc.2":"2021-08-04T13:52:47.792Z","0.4.2-rc.3":"2021-08-05T11:48:15.954Z","0.4.2-rc.6":"2021-08-09T16:32:30.331Z","0.4.2-rc.8":"2021-08-10T07:19:29.136Z","0.4.2-rc.10":"2021-08-10T09:09:48.678Z","0.4.2-rc.11":"2021-08-11T09:22:43.669Z","0.5.0":"2021-08-11T15:11:40.713Z","0.5.1-rc.4":"2021-08-12T10:50:58.281Z","0.5.1-rc.5":"2021-08-12T11:07:15.043Z","0.5.1-rc.6":"2021-08-12T14:10:51.987Z","0.5.1-rc.7":"2021-08-16T15:47:17.684Z","0.6.0":"2021-08-17T10:42:36.440Z","0.5.1-rc.9":"2021-08-17T10:52:10.637Z","0.5.1-rc.10":"2021-08-17T11:09:35.635Z","0.6.1-rc.1":"2021-08-17T12:56:05.332Z","0.4.2":"2021-08-17T14:10:05.502Z","0.5.2":"2021-08-17T17:18:06.009Z","0.6.1":"2021-08-17T19:58:36.020Z","0.6.2-rc.1":"2021-08-17T21:55:56.912Z","0.6.2-rc.3":"2021-08-25T07:32:29.171Z","0.6.2-rc.4":"2021-08-25T08:52:54.982Z","0.6.2":"2021-08-25T15:56:11.493Z","0.6.3-rc.2":"2021-08-26T09:48:15.193Z","0.6.3-rc.3":"2021-08-26T11:10:08.394Z","0.6.3-rc.4":"2021-08-26T13:58:15.889Z","0.6.3-rc.5":"2021-08-26T15:43:11.982Z","0.6.3-rc.6":"2021-08-31T13:35:00.275Z","0.6.3-rc.7":"2021-09-02T14:59:56.958Z","0.6.3-rc.8":"2021-09-02T17:39:01.054Z","0.6.3":"2021-09-02T18:18:57.621Z","0.6.4-rc.1":"2021-09-06T11:19:02.945Z","0.6.4-rc.2":"2021-09-06T15:02:09.401Z","0.6.4-rc.4":"2021-09-07T17:03:46.390Z","0.6.4-rc.5":"2021-09-08T09:33:24.415Z","0.6.4":"2021-09-08T10:02:09.334Z","0.6.5-rc.1":"2021-09-14T13:40:13.827Z","0.6.5-rc.4":"2021-09-17T12:50:50.852Z","0.6.5":"2021-09-17T13:24:06.117Z","0.6.6-rc.0":"2021-09-17T13:30:13.514Z","0.6.7-rc.0":"2021-09-17T16:25:31.626Z","0.6.6":"2021-09-17T16:36:04.527Z","0.6.7-rc.1":"2021-09-21T16:10:45.875Z","0.6.7-rc.12":"2021-09-23T06:16:09.387Z","0.6.7-rc.13":"2021-09-23T06:26:33.607Z","0.6.7-rc.14":"2021-09-23T10:47:53.911Z","0.6.7-rc.15":"2021-09-23T12:56:50.481Z","0.6.7-rc.16":"2021-09-23T18:33:12.117Z","0.6.7-rc.17":"2021-09-24T11:20:45.497Z","0.6.7-rc.18":"2021-09-24T12:45:33.823Z","0.7.0":"2021-09-24T12:49:13.701Z","0.7.1-rc.0":"2021-09-24T12:53:37.376Z","0.7.1-rc.1":"2021-09-25T17:26:13.161Z","0.7.1-rc.2":"2021-09-25T18:11:09.527Z","0.7.1-rc.3":"2021-09-27T16:37:28.385Z","0.7.1-rc.5":"2021-09-28T12:00:13.681Z","0.7.1":"2021-09-28T12:02:57.351Z","0.7.2-rc.0":"2021-09-28T12:07:40.605Z","0.7.2-rc.1":"2021-09-30T15:48:52.074Z","0.7.2-rc.2":"2021-09-30T17:39:11.285Z","0.7.2-rc.3":"2021-10-02T12:58:13.954Z","0.7.2-rc.4":"2021-10-08T14:33:01.111Z","0.7.2-rc.5":"2021-11-04T07:26:17.934Z","0.7.2-rc.6":"2021-11-12T11:31:13.160Z","0.7.2":"2021-11-12T11:54:13.795Z","0.7.3-rc.0":"2021-11-12T11:56:07.721Z","0.7.3-rc.1":"2021-11-19T15:42:09.959Z","0.7.3":"2021-11-19T15:45:59.330Z","0.7.4-rc.0":"2021-11-19T15:48:29.522Z","0.7.4-rc.1":"2021-11-19T17:23:32.035Z","0.7.4-rc.2":"2021-11-22T16:17:20.953Z","0.7.4-rc.3":"2021-11-24T09:35:44.392Z","0.7.4":"2021-11-24T09:37:47.720Z","0.7.5-rc.0":"2021-11-24T09:39:36.033Z","0.7.5-rc.1":"2021-12-03T10:51:56.800Z","0.7.5-rc.2":"2021-12-03T13:26:24.520Z","0.7.5-rc.3":"2021-12-03T14:05:30.443Z","0.7.5-rc.4":"2021-12-03T15:01:36.657Z","0.7.5-rc.5":"2021-12-06T10:37:48.774Z","0.7.5-rc.6":"2021-12-06T16:28:54.634Z","0.7.5-rc.7":"2021-12-06T22:23:39.428Z","0.7.5-rc.8":"2021-12-13T11:34:33.266Z","0.7.5-rc.9":"2021-12-13T12:09:36.265Z","0.7.5-rc.11":"2021-12-15T12:50:22.174Z","0.7.5-rc.10":"2021-12-15T12:50:39.872Z","0.7.5-rc.12":"2021-12-15T12:53:01.311Z","0.7.5-rc.13":"2021-12-15T18:25:10.673Z","0.8.0":"2021-12-15T20:27:26.462Z","0.8.1-rc.0":"2021-12-15T20:29:48.544Z","0.8.1-rc.1":"2021-12-16T09:06:39.144Z","0.8.1-rc.2":"2021-12-17T09:57:14.354Z","0.8.1-rc.3":"2022-01-13T18:31:14.110Z","0.8.1-rc.4":"2022-01-20T14:26:31.853Z","0.8.1-rc.5":"2022-01-21T15:46:04.084Z","0.8.1-7fe0da57f.0":"2022-01-26T12:13:42.207Z","0.8.1-5439a0e.0":"2022-01-26T13:07:30.864Z","0.8.1-a6b201af.0":"2022-01-27T15:37:22.426Z","0.8.1-fbe14923.0":"2022-01-27T18:17:24.185Z","0.8.1-6cb3a87e.0":"2022-01-27T19:12:33.269Z","0.8.2-2afef2eb.0":"2022-01-27T20:08:53.965Z","0.8.2-3a5d61d4.0":"2022-01-27T21:33:37.827Z","0.8.1-cca6e321.0":"2022-01-27T23:03:43.272Z","0.8.1":"2022-01-27T23:17:37.929Z","0.8.2-8d260215.0":"2022-01-27T23:52:55.342Z","0.8.2-2c8ec080.0":"2022-01-28T14:56:21.629Z","0.8.2-3a74c110.0":"2022-02-04T16:17:01.069Z","0.8.2-383dc07d.0":"2022-02-04T19:57:07.646Z","0.8.2-709831f6.0":"2022-02-06T16:03:21.740Z","0.8.2":"2022-02-07T16:51:23.101Z","0.8.3-1082fce9.0":"2022-02-18T16:14:58.340Z","0.8.3-125d42ba.0":"2022-03-01T09:46:55.031Z","0.8.3-df1bd1bb.0":"2022-03-01T11:11:10.631Z","0.8.3":"2022-04-05T15:10:10.956Z","0.8.4-e90b8f13.0":"2022-04-05T16:10:01.273Z","0.8.4-8f7ce23c.0":"2022-04-20T12:40:12.284Z","0.8.4":"2022-04-26T07:02:02.945Z","0.8.5-7165bf71.0":"2022-05-16T20:07:53.368Z","0.8.5-4e93dd5d.0":"2022-05-27T13:43:07.512Z","0.8.5-919b27a8.0":"2022-05-27T16:18:34.620Z","0.9.0":"2022-05-30T19:17:19.528Z","0.9.1-ddfb899f.0":"2022-05-30T19:56:57.363Z","0.9.1-764b4adc.0":"2022-06-01T14:26:20.722Z","0.9.1-be025c89.0":"2022-06-01T14:31:32.263Z","0.9.1-87e00a69.0":"2022-06-01T14:36:14.208Z","0.9.1":"2022-06-01T15:16:25.144Z","0.9.2-70e142ac.0":"2022-06-13T16:00:31.976Z","0.9.2":"2022-06-14T06:25:23.476Z","0.9.3-7be50bd1.0":"2022-06-22T17:48:34.591Z","0.9.3":"2022-06-23T12:03:13.650Z","0.9.4-00bd3dd0.0":"2022-06-24T09:30:46.883Z","0.9.4":"2022-06-24T10:25:24.969Z","0.9.5-a05695fc.0":"2022-07-20T13:22:17.879Z","0.9.5-39dbf708.0":"2022-08-17T21:43:04.275Z","0.9.5-8f351a89.0":"2022-08-17T23:18:56.704Z","0.9.5-83f9882e.0":"2022-09-06T11:30:39.970Z","0.9.5-051da161.0":"2022-09-07T12:55:36.555Z","0.10.0":"2022-09-07T13:38:03.149Z","0.10.1-b5456882.0":"2022-09-16T09:24:21.444Z","0.10.1-7c676f63.0":"2022-09-21T19:16:30.636Z","0.10.1-2a830bf5.0":"2022-09-21T20:54:09.242Z","0.10.1-7304a0f4.0":"2022-09-21T20:54:50.515Z","0.10.1":"2022-09-21T21:55:03.128Z","0.10.2-d75e0a39.0":"2022-09-22T08:52:16.125Z","0.10.2-d1b0a8a7.0":"2022-09-22T10:41:53.296Z","0.10.2-acbc1c62.0":"2022-09-22T12:59:57.616Z","0.10.2-dfc43d4e.0":"2022-09-26T14:20:26.518Z","0.10.2-0cee4a4c.0":"2022-10-24T09:13:32.168Z","0.11.0":"2022-10-24T10:47:33.416Z","0.11.1-a77e40cc.0":"2022-10-25T07:11:32.641Z","0.11.1-58e6f468.0":"2022-10-25T08:15:47.649Z","0.11.1-6ae5eb7d.0":"2022-10-28T07:29:54.421Z","0.11.1-6be59068.0":"2022-11-17T19:47:59.449Z","0.0.1-563806f1.0":"2023-01-09T18:11:17.273Z","0.0.1-e85e5b6e.0":"2023-01-09T19:16:09.820Z","0.0.1-2a6fede5.0":"2023-01-10T09:35:58.887Z","0.11.0-5f73ecad":"2023-01-10T17:14:56.071Z","0.11.0-4b4c124c":"2023-01-11T16:06:17.651Z","0.11.0-789ee585":"2023-01-11T17:05:53.295Z","0.11.0-fa578bac":"2023-01-11T17:50:40.033Z","0.11.0-d1c3abb3":"2023-01-11T18:09:16.024Z","0.12.0":"2023-01-12T11:37:03.922Z","0.12.0-6eeb1be5":"2023-01-13T18:21:01.454Z","0.12.0-ab02e8f8":"2023-01-17T12:24:41.036Z","0.12.0-3bcabe38":"2023-01-17T15:32:00.588Z","0.12.0-b64d4af0":"2023-02-01T11:24:46.376Z","0.12.0-e64813f6":"2023-05-24T18:46:06.595Z","0.12.0-4694e806":"2023-05-25T11:32:04.482Z","0.12.0-6d95ce08":"2023-05-25T12:10:57.725Z","0.12.0-7b79c1b8":"2023-05-25T12:46:40.308Z","0.12.1":"2023-05-25T15:00:03.391Z"},"maintainers":[{"email":"alex@achingbrain.net","name":"achingbrain"},{"email":"npm-service-account+ipfs@protocol.ai","name":"npm-service-account-ipfs"}],"license":"Apache-2.0 OR MIT","readme":"> # ⛔️ DEPRECATED: [js-IPFS](https://github.com/ipfs/js-ipfs) has been superseded by [Helia](https://github.com/ipfs/helia)\n>\n> 📚 [Learn more about this deprecation](https://github.com/ipfs/js-ipfs/issues/4336) or [how to migrate](https://github.com/ipfs/helia/wiki/Migrating-from-js-IPFS)\n>\n> ⚠️ If you continue using this repo, please note that security fixes will not be provided\n\n# ipfs-grpc-server <!-- omit in toc -->\n\n[![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech)\n[![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech)\n[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-ipfs.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-ipfs)\n[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/js-ipfs/test.yml?branch=master\\&style=flat-square)](https://github.com/ipfs/js-ipfs/actions/workflows/test.yml?query=branch%3Amaster)\n\n> A server library for the IPFS gRPC API\n\n## Table of contents <!-- omit in toc -->\n\n- [Install](#install)\n- [Why?](#why)\n- [Protocol](#protocol)\n  - [1. Metadata](#1-metadata)\n  - [2. Messages](#2-messages)\n    - [Signal](#signal)\n    - [Header](#header)\n    - [Message data](#message-data)\n    - [Trailer](#trailer)\n- [Handlers](#handlers)\n  - [Metadata](#metadata)\n  - [Unary](#unary)\n  - [Server streaming](#server-streaming)\n  - [Client streaming](#client-streaming)\n  - [Bidirectional streaming](#bidirectional-streaming)\n- [License](#license)\n- [Contribute](#contribute)\n\n## Install\n\n```console\n$ npm i ipfs-grpc-server\n```\n\n## Why?\n\n[gRPC-web](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md) allows us to form HTTP requests out of gRPC invocations, but the [official implementation](https://github.com/grpc/grpc-web) supports only unary calls and server streaming, which in terms of functionality doesn't give us much over the existing [ipfs-http-client](https://www.npmjs.com/package/ipfs-http-client).\n\nIn order to support streaming file uploads with errors, pubsub, etc, bi-directional streaming is required.  We can either use Websockets for this, or use two connections, one for upload and one for download though this involves two requests for every operation and some orchestration on the server side to match one up with the other.\n\nWebsockets are a cheaper and simpler way of accomplishing the same thing though sadly the official gRPC implementation has [no plans](https://github.com/grpc/grpc-web/blob/master/doc/streaming-roadmap.md#issues-with-websockets) to implement full-duplex streaming in this way.\n\nThis module implements a Websocket proxy for a gRPC-web server.  It's a js port of the [grpcwebproxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy) project from [improbable-eng/grpc-web](https://github.com/improbable-eng/grpc-web).\n\n## Protocol\n\nEvery RPC invocation opens a new WebSocket connection, the invocation is completed and the socket connection is closed.\n\nThe connection is opened against the path of the RPC method the client wishes to invoke.  The path is created from the protobuf service definition package, service and procedure name.\n\nE.g. given the following service definition:\n\n```protobuf\npackage ipfs;\n\nservice Root {\n  rpc id (Req) returns (Res) {}\n}\n```\n\nA path of `/ipfs.Root/id` would be created.\n\nThere are three parts to the communication, metadata, messages and trailers.  Communication is symmetrical; that is, the client sends metadata, one or more messages and finally some trailers and the server responds with metadata, one or more messages and finally some trailers.\n\nThe amount of messages a client/server can send is dictated by if the RPC method is unary or streaming and if so in which direction.\n\nUnary will result in one message sent and one received, client streaming is many sent and one received, server streaming is one sent and many received and finally bidirectional is many sent and many received.\n\n### 1. Metadata\n\nMetadata is sent as the first websocket message. It is a utf8 encoded list in the same format as [HTTP Headers][]\n\n### 2. Messages\n\nOne ore more messages will be sent.  Messages are sent as a single websocket message and contain a signal, a header, some message data and an optional trailer.\n\nEvery message sent to or received from the server will have the following format:\n\n| byte index | Notes        |\n| ---------- | ------------ |\n| 0          | Signal       |\n| 1-5        | Header       |\n| n1-n2      | Message data |\n| n3-n3+5    | Trailer      |\n\n#### Signal\n\nA one-byte field.\n\n| Value | Meaning                                                               |\n| ----- | --------------------------------------------------------------------- |\n| 0     | START\\_SEND: Further messages will be sent as part of this context    |\n| 1     | FINISH\\_SEND: This is the final message, no further data will be sent |\n\n#### Header\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                                        |\n| ---------- | ------------------------------------------------------------------------------ |\n| 0          | 0: This is a header, 128: This is a footer                                     |\n| 1-4        | An unsigned big-endian 32-bit integer that specifies the length of the message |\n\n#### Message data\n\nA protocol buffer message, the length of which is defined in the header\n\n#### Trailer\n\nA five-byte field that contains one byte signifying if it's a Header or a Trailer and four bytes that contain the length of the following data.\n\n| byte index | Meaning                                                              |\n| ---------- | -------------------------------------------------------------------- |\n| 0          | 0: This is a header, 128: This is a footer                           |\n| 1-4        | A big-endian 32-bit integer that specifies the length of the trailer |\n\nThe trailer contains [HTTP headers][] as a utf8 encoded string in the same way as invocation metadata.\n\n## Handlers\n\nMethod handlers come in four flavours - unary, server streaming, client streaming, bidirectional streaming and accept metadata as an argument.\n\n### Metadata\n\nAll methods accept metadata which are sent as the equivalent of HTTP headers as part of every request.  These are accepted by the client as options to a given method.\n\nE.g.:\n\n```js\nipfs.addAll(source, options)\n// `source` will be turned into a message stream\n// `options` will be sent as metadata\n```\n\n### Unary\n\nThe simplest case, one request message and one response message.\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function handler (request, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Server streaming\n\nWhere the server sends multiple messages.  `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function serverStreamingHandler (request, sink, metadata) {\n    sink.push(..)\n    sink.push(..)\n\n    sink.end()\n  }\n\n  return clientStreamingHandler\n}\n```\n\n### Client streaming\n\nWhere the client sends multiple messages.  `source` is an [AsyncIterator][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function clientStreamingHandler (source, metadata) {\n    const response = {\n      //... some fields here\n    }\n\n    for await (const thing of source) {\n      // do something with `thing`\n    }\n\n    return response\n  }\n\n  return handler\n}\n```\n\n### Bidirectional streaming\n\nWhere the client and the server both send multiple messages.  `source` is an [AsyncIterator][] and `sink` is an [it-pushable][].\n\n```javascript\nexport function grpcFunction (ipfs, options = {}) {\n  async function bidirectionalHandler (source, sink, metadata) {\n    for await (const thing of source) {\n      sink.push(sink)\n    }\n\n    sink.end()\n  }\n\n  return bidirectionalHandler\n}\n```\n\n## License\n\nLicensed under either of\n\n- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)\n\n## Contribute\n\nContributions welcome! Please check out [the issues](https://github.com/ipfs/js-ipfs/issues).\n\nAlso see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.\n\nPlease be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n\n[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)\n\n[HTTP headers]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n[it-pushable]: https://www.npmjs.com/package/it-pushable\n\n[AsyncIterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator\n","readmeFilename":"README.md","description":"A server library for the IPFS gRPC API","homepage":"https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-grpc-server#readme","keywords":["ipfs"],"repository":{"type":"git","url":"git+https://github.com/ipfs/js-ipfs.git"},"bugs":{"url":"https://github.com/ipfs/js-ipfs/issues"}}