bare-rpc 0.1.4 → 0.2.0
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/index.d.ts +9 -7
- package/index.js +11 -2
- package/lib/command-router.js +49 -0
- package/lib/errors.js +4 -0
- package/lib/incoming-request.js +19 -5
- package/lib/messages.js +3 -3
- package/lib/outgoing-request.js +23 -5
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ReadableOptions,
|
|
5
5
|
Writable,
|
|
6
6
|
WritableOptions,
|
|
7
|
-
|
|
7
|
+
Duplex
|
|
8
8
|
} from 'bare-stream'
|
|
9
9
|
|
|
10
10
|
declare const constants: {
|
|
@@ -26,9 +26,10 @@ declare const constants: {
|
|
|
26
26
|
interface RPCIncomingRequest {
|
|
27
27
|
readonly rpc: RPC
|
|
28
28
|
readonly id: number
|
|
29
|
-
readonly command:
|
|
29
|
+
readonly command: number
|
|
30
30
|
readonly data: Buffer
|
|
31
31
|
readonly sent: boolean
|
|
32
|
+
readonly received: boolean
|
|
32
33
|
|
|
33
34
|
reply(data: Buffer | string, encoding?: BufferEncoding): void
|
|
34
35
|
|
|
@@ -37,14 +38,15 @@ interface RPCIncomingRequest {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
declare class RPCIncomingRequest {
|
|
40
|
-
constructor(rpc: RPC, id: number, command:
|
|
41
|
+
constructor(rpc: RPC, id: number, command: number, data: Buffer)
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
interface RPCOutgoingRequest {
|
|
44
45
|
readonly rpc: RPC
|
|
45
46
|
readonly id: number
|
|
46
|
-
readonly command:
|
|
47
|
+
readonly command: number
|
|
47
48
|
readonly sent: boolean
|
|
49
|
+
readonly received: boolean
|
|
48
50
|
|
|
49
51
|
send(data: Buffer | string, encoding?: BufferEncoding): void
|
|
50
52
|
|
|
@@ -55,7 +57,7 @@ interface RPCOutgoingRequest {
|
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
declare class RPCOutgoingRequest {
|
|
58
|
-
constructor(rpc: RPC, command:
|
|
60
|
+
constructor(rpc: RPC, command: number)
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
declare class RPCIncomingStream extends Readable {
|
|
@@ -77,11 +79,11 @@ declare class RPCOutgoingStream extends Writable {
|
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
interface RPC {
|
|
80
|
-
request(command:
|
|
82
|
+
request(command: number): RPCOutgoingRequest
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
declare class RPC {
|
|
84
|
-
constructor(stream:
|
|
86
|
+
constructor(stream: Duplex, onrequest: (req: RPCIncomingRequest) => void)
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
export = RPC
|
package/index.js
CHANGED
|
@@ -7,8 +7,9 @@ const IncomingRequest = require('./lib/incoming-request')
|
|
|
7
7
|
const IncomingStream = require('./lib/incoming-stream')
|
|
8
8
|
const OutgoingRequest = require('./lib/outgoing-request')
|
|
9
9
|
const OutgoingStream = require('./lib/outgoing-stream')
|
|
10
|
+
const CommandRouter = require('./lib/command-router')
|
|
10
11
|
|
|
11
|
-
module.exports = class RPC {
|
|
12
|
+
module.exports = exports = class RPC {
|
|
12
13
|
constructor(stream, onrequest) {
|
|
13
14
|
this._stream = stream
|
|
14
15
|
|
|
@@ -23,7 +24,13 @@ module.exports = class RPC {
|
|
|
23
24
|
|
|
24
25
|
this._buffer = null
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
if (typeof onrequest === 'function') {
|
|
28
|
+
onrequest = onrequest.bind(this)
|
|
29
|
+
} else {
|
|
30
|
+
onrequest = onrequest._onrequest.bind(onrequest)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
this._onrequest = onrequest
|
|
27
34
|
this._ondata = this._ondata.bind(this)
|
|
28
35
|
|
|
29
36
|
this._stream.on('data', this._ondata)
|
|
@@ -357,3 +364,5 @@ module.exports = class RPC {
|
|
|
357
364
|
stream.destroy(message.error)
|
|
358
365
|
}
|
|
359
366
|
}
|
|
367
|
+
|
|
368
|
+
exports.CommandRouter = CommandRouter
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const c = require('compact-encoding')
|
|
2
|
+
|
|
3
|
+
module.exports = class RPCCommandRouter {
|
|
4
|
+
constructor(opts = {}) {
|
|
5
|
+
const { valueEncoding = c.raw } = opts
|
|
6
|
+
|
|
7
|
+
this._responders = new Map()
|
|
8
|
+
this._defaultValueEncoding = valueEncoding
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
respond(command, opts = {}, onrequest) {
|
|
12
|
+
if (typeof opts === 'function') {
|
|
13
|
+
onrequest = opts
|
|
14
|
+
opts = {}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
valueEncoding = this._defaultValueEncoding,
|
|
19
|
+
requestEncoding = valueEncoding,
|
|
20
|
+
responseEncoding = valueEncoding
|
|
21
|
+
} = opts
|
|
22
|
+
|
|
23
|
+
this._responders.set(command, {
|
|
24
|
+
onrequest,
|
|
25
|
+
requestEncoding,
|
|
26
|
+
responseEncoding
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async _onrequest(req) {
|
|
31
|
+
const responder = this._responders.get(req.command)
|
|
32
|
+
|
|
33
|
+
if (responder === undefined) return
|
|
34
|
+
|
|
35
|
+
const { onrequest, requestEncoding, responseEncoding } = responder
|
|
36
|
+
|
|
37
|
+
let data = req.data
|
|
38
|
+
|
|
39
|
+
if (requestEncoding) data = c.decode(requestEncoding, data)
|
|
40
|
+
|
|
41
|
+
data = await onrequest(req, req.data)
|
|
42
|
+
|
|
43
|
+
if (req.sent) return
|
|
44
|
+
|
|
45
|
+
if (responseEncoding) data = c.encode(responseEncoding, data)
|
|
46
|
+
|
|
47
|
+
req.reply(data)
|
|
48
|
+
}
|
|
49
|
+
}
|
package/lib/errors.js
CHANGED
|
@@ -19,4 +19,8 @@ module.exports = class RPCError extends Error {
|
|
|
19
19
|
static ALREADY_SENT(msg) {
|
|
20
20
|
return new RPCError(msg, 'ALREADY_SENT', RPCError.ALREADY_SENT)
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
static ALREADY_RECEIVED(msg) {
|
|
24
|
+
return new RPCError(msg, 'ALREADY_RECEIVED', RPCError.ALREADY_RECEIVED)
|
|
25
|
+
}
|
|
22
26
|
}
|
package/lib/incoming-request.js
CHANGED
|
@@ -8,13 +8,17 @@ module.exports = class RPCIncomingRequest {
|
|
|
8
8
|
this.command = command
|
|
9
9
|
this.data = data
|
|
10
10
|
this.sent = false
|
|
11
|
+
this.received = false
|
|
11
12
|
|
|
12
13
|
this._requestStream = null
|
|
13
14
|
this._responseStream = null
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
reply(data, encoding) {
|
|
17
|
-
if (this.sent)
|
|
18
|
+
if (this.sent) {
|
|
19
|
+
throw errors.ALREADY_SENT('Response has already been sent')
|
|
20
|
+
}
|
|
21
|
+
|
|
18
22
|
this.sent = true
|
|
19
23
|
|
|
20
24
|
this.rpc._sendResponse(
|
|
@@ -24,15 +28,25 @@ module.exports = class RPCIncomingRequest {
|
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
createResponseStream(opts = {}) {
|
|
27
|
-
if (this.
|
|
28
|
-
|
|
31
|
+
if (this.sent) {
|
|
32
|
+
throw errors.ALREADY_SENT('Response has already been sent')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.sent = true
|
|
36
|
+
|
|
37
|
+
this.rpc._createResponseStream(this, true, opts)
|
|
29
38
|
|
|
30
39
|
return this._responseStream
|
|
31
40
|
}
|
|
32
41
|
|
|
33
42
|
createRequestStream(opts = {}) {
|
|
34
|
-
if (this.
|
|
35
|
-
|
|
43
|
+
if (this.received) {
|
|
44
|
+
throw errors.ALREADY_RECEIVED('Request has already been received')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.received = true
|
|
48
|
+
|
|
49
|
+
this.rpc._createRequestStream(this, false, opts)
|
|
36
50
|
|
|
37
51
|
return this._requestStream
|
|
38
52
|
}
|
package/lib/messages.js
CHANGED
|
@@ -4,17 +4,17 @@ const errors = require('./errors')
|
|
|
4
4
|
|
|
5
5
|
const request = {
|
|
6
6
|
preencode(state, m) {
|
|
7
|
-
c.
|
|
7
|
+
c.uint.preencode(state, m.command)
|
|
8
8
|
c.uint.preencode(state, m.stream)
|
|
9
9
|
if (m.stream === 0) c.buffer.preencode(state, m.data)
|
|
10
10
|
},
|
|
11
11
|
encode(state, m) {
|
|
12
|
-
c.
|
|
12
|
+
c.uint.encode(state, m.command)
|
|
13
13
|
c.uint.encode(state, m.stream)
|
|
14
14
|
if (m.stream === 0) c.buffer.encode(state, m.data)
|
|
15
15
|
},
|
|
16
16
|
decode(state, id) {
|
|
17
|
-
const command = c.
|
|
17
|
+
const command = c.uint.decode(state)
|
|
18
18
|
const stream = c.uint.decode(state)
|
|
19
19
|
const data = stream === 0 ? c.buffer.decode(state) : null
|
|
20
20
|
|
package/lib/outgoing-request.js
CHANGED
|
@@ -7,6 +7,7 @@ module.exports = class RPCOutgoingRequest {
|
|
|
7
7
|
this.id = id
|
|
8
8
|
this.command = command
|
|
9
9
|
this.sent = false
|
|
10
|
+
this.received = false
|
|
10
11
|
|
|
11
12
|
this._promise = new Promise((resolve, reject) => {
|
|
12
13
|
this._resolve = resolve
|
|
@@ -18,7 +19,10 @@ module.exports = class RPCOutgoingRequest {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
send(data, encoding) {
|
|
21
|
-
if (this.sent)
|
|
22
|
+
if (this.sent) {
|
|
23
|
+
throw errors.ALREADY_SENT('Request has already been sent')
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
this.sent = true
|
|
23
27
|
|
|
24
28
|
this.rpc._sendRequest(
|
|
@@ -28,24 +32,38 @@ module.exports = class RPCOutgoingRequest {
|
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
reply(encoding) {
|
|
35
|
+
if (this.received) {
|
|
36
|
+
throw errors.ALREADY_RECEIVED('Response is already being received')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.received = true
|
|
40
|
+
|
|
31
41
|
return encoding && encoding !== 'buffer'
|
|
32
42
|
? this._promise.then((data) => b4a.toString(data, encoding))
|
|
33
43
|
: this._promise
|
|
34
44
|
}
|
|
35
45
|
|
|
36
46
|
createRequestStream(opts = {}) {
|
|
37
|
-
if (this.
|
|
38
|
-
|
|
47
|
+
if (this.sent) {
|
|
48
|
+
throw errors.ALREADY_SENT('Request has already been sent')
|
|
39
49
|
}
|
|
40
50
|
|
|
51
|
+
this.sent = true
|
|
52
|
+
|
|
53
|
+
this.rpc._createRequestStream(this, true, opts)
|
|
54
|
+
|
|
41
55
|
return this._requestStream
|
|
42
56
|
}
|
|
43
57
|
|
|
44
58
|
createResponseStream(opts = {}) {
|
|
45
|
-
if (this.
|
|
46
|
-
|
|
59
|
+
if (this.received) {
|
|
60
|
+
throw errors.ALREADY_RECEIVED('Response has already been received')
|
|
47
61
|
}
|
|
48
62
|
|
|
63
|
+
this.received = true
|
|
64
|
+
|
|
65
|
+
this.rpc._createResponseStream(this, false, opts)
|
|
66
|
+
|
|
49
67
|
return this._responseStream
|
|
50
68
|
}
|
|
51
69
|
}
|