bare-rpc 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,6 +6,148 @@
6
6
  npm i bare-rpc
7
7
  ```
8
8
 
9
+ ## Usage
10
+
11
+ ```js
12
+ import RPC from 'bare-rpc'
13
+
14
+ const rpc = new RPC(stream, (req) => {
15
+ if (req.command === 42) {
16
+ console.log(req.data.toString()) // ping
17
+ req.reply('pong')
18
+ }
19
+ })
20
+
21
+ // On the other end
22
+ const req = rpc.request(42)
23
+ req.send('ping')
24
+
25
+ const replyBuffer = await req.reply()
26
+ console.log(replyBuffer.toString()) // pong
27
+ ```
28
+
29
+ ## API
30
+
31
+ ### `RPC`
32
+
33
+ #### `const rpc = new RPC(stream, [onrequest])`
34
+
35
+ Create an RPC instance using a duplex `stream`. `onrequest` is an optional callback run when a remote request is received. This is where processing and responding to an RPC request happens. `onrequest` receives a `RPCIncomingRequest` as an argument, for example:
36
+
37
+ ```js
38
+ const rpc = new RPC(stream, (req) => {
39
+ if (req.command === 42) {
40
+ req.reply('pong')
41
+ }
42
+ })
43
+ ```
44
+
45
+ See [`RPCIncomingRequest`](#rpcincomingrequest) for properties and methods for processing the request.
46
+
47
+ `onrequest` can also be a [`RPCCommandRouter`](#rpccommandrouter).
48
+
49
+ #### `const req = rpc.request(command)`
50
+
51
+ Create a request for `command`. `command` is a unique number that should be used to differentiate different requests on the remote end. Returns a `RPCOutgoingRequest`.
52
+
53
+ ### `RPCOutgoingRequest`
54
+
55
+ #### `req.command`
56
+
57
+ The command that the request was created with. A command is a unique number.
58
+
59
+ #### `req.sent`
60
+
61
+ A boolean for whether the request has been sent.
62
+
63
+ #### `req.received`
64
+
65
+ A boolean for whether the request has received a reply.
66
+
67
+ #### `req.send(data, [encoding])`
68
+
69
+ Send the request with the provided `data`. `data` can be a buffer or a string which will be encoded using `encoding`.
70
+
71
+ `.send()` can only be called once per request.
72
+
73
+ #### `const data = await req.reply([encoding])`
74
+
75
+ Await the reply from the remote end to the request. `encoding` can be defined for decoding the response `data` buffer back into a string.
76
+
77
+ #### `const stream = req.createRequestStream([opts])`
78
+
79
+ Create a [`Writable`](https://github.com/mafintosh/streamx?tab=readme-ov-file#writable-stream) stream for sending data with the request.
80
+
81
+ #### `const stream = req.createResponseStream([opts])`
82
+
83
+ Create a [`Readable`](https://github.com/mafintosh/streamx?tab=readme-ov-file#readable-stream) stream for receiving data in reply to the request.
84
+
85
+ ### `RPCIncomingRequest`
86
+
87
+ #### `req.command`
88
+
89
+ The command that the request was sent as. A command is a unique number.
90
+
91
+ #### `req.data`
92
+
93
+ The data buffer sent with the request.
94
+
95
+ #### `req.sent`
96
+
97
+ A boolean for whether a reply has been sent.
98
+
99
+ #### `req.received`
100
+
101
+ A boolean for whether the request has been received as a stream. See [`req.createRequestStream()`](#const-stream--reqcreaterequeststream) for receiving requests as a stream.
102
+
103
+ #### `req.reply(data, [encoding])`
104
+
105
+ Reply to the request with the provided `data`. `data` can be a buffer or a string which will be encoded using `encoding`.
106
+
107
+ #### `const stream = req.createRequestStream([opts])`
108
+
109
+ Create a `Readable` stream for receiving data from the request.
110
+
111
+ #### `const stream = req.createResponseStream([opts])`
112
+
113
+ Create a `Writable` stream for sending data in reply to the request.
114
+
115
+ ### `RPCCommandRouter`
116
+
117
+ An alternative way to define commands and handlers for receiving them.
118
+
119
+ #### `const router = new RPC.CommandRouter()`
120
+
121
+ Create a new command router. This router can then be used when creating an
122
+ `rpc`. For example:
123
+
124
+ ```js
125
+ const router = new RPC.CommandRouter()
126
+
127
+ router.respond(42, (req, data) => {
128
+ console.log(data.toString()) // ping
129
+
130
+ return Buffer.from('pong')
131
+ })
132
+
133
+ const rpc = new RPC(stream, router)
134
+ const req = rpc.request(42)
135
+ req.send('ping')
136
+ ```
137
+
138
+ #### `router.respond(command, [opts], async (req, data) => {})`
139
+
140
+ Define a command and the handler for it. The callback for a command receives both the request (`req`) and the `data` buffer and can return a value to respond. If the request is responded to in the callback, the return value is ignored.
141
+
142
+ `opts` can include:
143
+
144
+ ```
145
+ {
146
+ requestEncoding: c.raw, // Encoding for decoding incoming request
147
+ responseEncoding: c.raw, // Encoding for outgoing response
148
+ }
149
+ ```
150
+
9
151
  ## License
10
152
 
11
153
  Apache-2.0
package/index.d.ts CHANGED
@@ -50,7 +50,7 @@ interface RPCOutgoingRequest {
50
50
 
51
51
  send(data: Buffer | string, encoding?: BufferEncoding): void
52
52
 
53
- reply(encoding?: BufferEncoding): Promise<Buffer>
53
+ reply(encoding?: BufferEncoding): Promise<Buffer | string>
54
54
 
55
55
  createRequestStream(opts?: WritableOptions): RPCOutgoingStream
56
56
  createResponseStream(opts?: ReadableOptions): RPCIncomingStream
package/index.js CHANGED
@@ -154,7 +154,7 @@ module.exports = exports = class RPC {
154
154
  }
155
155
 
156
156
  _onafterframe() {
157
- if (this._frame === -1 || this._buffered < this._frame) return
157
+ if (this._buffered < this._frame) return
158
158
 
159
159
  const buffer =
160
160
  this._buffer.length === 1 ? this._buffer[0] : b4a.concat(this._buffer)
@@ -169,7 +169,7 @@ module.exports = exports = class RPC {
169
169
  this._onbeforeframe()
170
170
  }
171
171
 
172
- _onmessage(buffer) {
172
+ async _onmessage(buffer) {
173
173
  let message
174
174
  try {
175
175
  message = m.message.decode(c.state(0, buffer.length, buffer))
@@ -189,7 +189,7 @@ module.exports = exports = class RPC {
189
189
  )
190
190
 
191
191
  try {
192
- this._onrequest(request)
192
+ await this._onrequest(request)
193
193
  } catch (err) {
194
194
  safetyCatch(err)
195
195
 
@@ -248,6 +248,11 @@ module.exports = exports = class RPC {
248
248
  }
249
249
 
250
250
  stream = request._requestStream
251
+
252
+ if (stream._pendingOpen === null) {
253
+ this._pendingRequests.add(message.id)
254
+ return
255
+ }
251
256
  } else if (message.stream & s.RESPONSE) {
252
257
  const request = this._outgoingResponses.get(message.id)
253
258
  if (request === undefined) {
@@ -256,6 +261,11 @@ module.exports = exports = class RPC {
256
261
  }
257
262
 
258
263
  stream = request._responseStream
264
+
265
+ if (stream._pendingOpen === null) {
266
+ this._pendingResponses.add(message.id)
267
+ return
268
+ }
259
269
  } else {
260
270
  return
261
271
  }
@@ -9,8 +9,6 @@ module.exports = class RPCIncomingStream extends Readable {
9
9
  this._request = request
10
10
  this._type = type
11
11
  this._mask = type === t.REQUEST ? s.REQUEST : s.RESPONSE
12
-
13
- this._pendingOpen = null
14
12
  }
15
13
 
16
14
  _open(cb) {
package/lib/messages.js CHANGED
@@ -53,16 +53,20 @@ const response = {
53
53
  c.bool.encode(state, !!m.error)
54
54
  c.uint.encode(state, m.stream)
55
55
 
56
- if (m.error) error.encode(state, m)
56
+ if (m.error) error.encode(state, m.error)
57
57
  else if (m.stream === 0) c.buffer.encode(state, m.data)
58
58
  },
59
59
  decode(state) {
60
- const error = c.bool.decode(state)
60
+ const err = c.bool.decode(state)
61
61
  const stream = c.uint.decode(state)
62
62
 
63
- if (error) return { stream, error: error.decode(state), data: null }
64
- if (stream === 0)
63
+ if (err) {
64
+ return { stream, error: error.decode(state), data: null }
65
+ }
66
+
67
+ if (stream === 0) {
65
68
  return { stream, error: null, data: c.buffer.decode(state) }
69
+ }
66
70
 
67
71
  return { stream, error: null, data: null }
68
72
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-rpc",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "librpc ABI compatible RPC for Bare",
5
5
  "exports": {
6
6
  ".": {
@@ -39,6 +39,7 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "bare-buffer": "^3.0.1",
42
+ "bare-ipc": "^1.1.0",
42
43
  "brittle": "^3.2.1",
43
44
  "prettier": "^3.4.2",
44
45
  "prettier-config-standard": "^7.0.0"