bare-rpc 0.0.1 → 0.1.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.js CHANGED
@@ -1,17 +1,20 @@
1
1
  const safetyCatch = require('safety-catch')
2
2
  const c = require('compact-encoding')
3
3
  const m = require('./lib/messages')
4
- const { type } = require('./lib/constants')
4
+ const { type: t, stream: s } = require('./lib/constants')
5
5
  const IncomingRequest = require('./lib/incoming-request')
6
+ const IncomingStream = require('./lib/incoming-stream')
6
7
  const OutgoingRequest = require('./lib/outgoing-request')
8
+ const OutgoingStream = require('./lib/outgoing-stream')
7
9
 
8
10
  module.exports = class RPC {
9
11
  constructor (stream, onrequest) {
10
12
  this._stream = stream
11
13
 
12
14
  this._id = 0
13
- this._responding = 0
14
15
  this._requests = new Map()
16
+ this._responses = new Map()
17
+ this._incoming = new Map()
15
18
 
16
19
  this._buffer = null
17
20
 
@@ -26,37 +29,72 @@ module.exports = class RPC {
26
29
  return new OutgoingRequest(this, command)
27
30
  }
28
31
 
29
- _send (request, data) {
30
- const id = ++this._id
32
+ _sendMessage (message) {
33
+ this._stream.write(c.encode(m.message, message))
34
+ }
35
+
36
+ _sendRequest (request, data = null) {
37
+ const id = request.id = ++this._id
31
38
 
32
39
  this._requests.set(id, request)
33
40
 
34
- this._stream.write(c.encode(m.message, {
35
- type: type.REQUEST,
41
+ this._sendMessage({
42
+ type: t.REQUEST,
36
43
  id,
37
44
  command: request.command,
45
+ stream: 0,
38
46
  data
39
- }))
47
+ })
40
48
  }
41
49
 
42
- _reply (request, data) {
43
- this._stream.write(c.encode(m.message, {
44
- type: type.RESPONSE,
50
+ _createRequestStream (request, isInitiator, opts) {
51
+ if (isInitiator) {
52
+ const id = request.id = ++this._id
53
+
54
+ this._requests.set(id, request)
55
+
56
+ request._requestStream = new OutgoingStream(this, request, t.REQUEST, opts)
57
+ } else {
58
+ this._incoming.set(request.id, request)
59
+
60
+ const stream = request._requestStream = new IncomingStream(this, request, t.REQUEST, opts)
61
+
62
+ stream.on('close', () => this._incoming.delete(request.id))
63
+ }
64
+ }
65
+
66
+ _sendResponse (request, data) {
67
+ this._sendMessage({
68
+ type: t.RESPONSE,
45
69
  id: request.id,
46
- error: false,
70
+ stream: 0,
71
+ error: null,
47
72
  data
48
- }))
73
+ })
74
+ }
75
+
76
+ _createResponseStream (request, isInitiator, opts) {
77
+ if (isInitiator) {
78
+ this._responses.set(request.id, request)
79
+
80
+ request._responseStream = new OutgoingStream(this, request, t.RESPONSE, opts)
81
+ } else {
82
+ this._incoming.set(request.id, request)
83
+
84
+ const stream = request._responseStream = new IncomingStream(this, request, t.RESPONSE, opts)
85
+
86
+ stream.on('close', () => this._incoming.delete(request.id))
87
+ }
49
88
  }
50
89
 
51
- _error (request, err) {
52
- this._stream.write(c.encode(m.message, {
53
- type: type.RESPONSE,
90
+ _sendError (request, err) {
91
+ this._sendMessage({
92
+ type: t.RESPONSE,
54
93
  id: request.id,
55
- error: true,
56
- message: err.message,
57
- code: err.code || '',
58
- status: err.errno || 0
59
- }))
94
+ stream: 0,
95
+ error: err,
96
+ data: null
97
+ })
60
98
  }
61
99
 
62
100
  _ondata (data) {
@@ -78,7 +116,7 @@ module.exports = class RPC {
78
116
  if (message === null) return
79
117
 
80
118
  switch (message.type) {
81
- case type.REQUEST: {
119
+ case t.REQUEST: {
82
120
  const request = new IncomingRequest(this, message.id, message.command, message.data)
83
121
 
84
122
  try {
@@ -86,18 +124,23 @@ module.exports = class RPC {
86
124
  } catch (err) {
87
125
  safetyCatch(err)
88
126
 
89
- this._error(request, err)
127
+ this._sendError(request, err)
90
128
  }
91
-
92
129
  break
93
130
  }
94
-
95
- case type.RESPONSE:
131
+ case t.RESPONSE:
96
132
  try {
97
133
  this._onresponse(message)
98
134
  } catch (err) {
99
135
  safetyCatch(err)
100
136
  }
137
+ break
138
+ case t.STREAM:
139
+ try {
140
+ this._onstream(message)
141
+ } catch (err) {
142
+ safetyCatch(err)
143
+ }
101
144
  }
102
145
 
103
146
  this._buffer = state.start === state.end ? null : this._buffer.subarray(state.start)
@@ -108,17 +151,164 @@ module.exports = class RPC {
108
151
  if (message.id === 0) return
109
152
 
110
153
  const request = this._requests.get(message.id)
111
-
112
154
  if (request === undefined) return
113
155
 
114
156
  if (message.error) {
115
- const err = new Error(`${message.message}`)
116
- err.code = message.code
117
- err.errno = message.status
157
+ request._reject(message.error)
158
+ } else if (message.stream === 0) {
159
+ request._resolve(message.data)
160
+ }
161
+ }
162
+
163
+ _onstream (message) {
164
+ if (message.id === 0) return
165
+
166
+ if (message.stream & s.OPEN) this._onstreamopen(message)
167
+ else if (message.stream & s.CLOSE) this._onstreamclose(message)
168
+ else if (message.stream & s.PAUSE) this._onstreampause(message)
169
+ else if (message.stream & s.RESUME) this._onstreamresume(message)
170
+ else if (message.stream & s.DATA) this._onstreamdata(message)
171
+ else if (message.stream & s.END) this._onstreamend(message)
172
+ else if (message.stream & s.DESTROY) this._onstreamdestroy(message)
173
+ }
174
+
175
+ _onstreamopen (message) {
176
+ let stream
118
177
 
119
- request._reject(err)
178
+ if (message.stream & s.REQUEST) {
179
+ const request = this._requests.get(message.id)
180
+ if (request === undefined) return
181
+
182
+ stream = request._requestStream
183
+ } else if (message.stream & s.RESPONSE) {
184
+ const request = this._responses.get(message.id)
185
+ if (request === undefined) return
186
+
187
+ stream = request._responseStream
120
188
  } else {
121
- request._resolve(message.data)
189
+ return
190
+ }
191
+
192
+ stream._continueOpen()
193
+ }
194
+
195
+ _onstreamclose (message) {
196
+ const request = this._incoming.get(message.id)
197
+ if (request === undefined) return
198
+
199
+ let stream
200
+
201
+ if (message.stream & s.REQUEST) {
202
+ stream = request._requestStream
203
+ } else if (message.stream & s.RESPONSE) {
204
+ stream = request._responseStream
205
+ } else {
206
+ return
207
+ }
208
+
209
+ if (message.error) stream.destroy(message.error)
210
+ else stream.push(null)
211
+ }
212
+
213
+ _onstreampause (message) {
214
+ let stream
215
+
216
+ if (message.stream & s.REQUEST) {
217
+ const request = this._requests.get(message.id)
218
+ if (request === undefined) return
219
+
220
+ stream = request._requestStream
221
+ } else if (message.stream & s.RESPONSE) {
222
+ const request = this._responses.get(message.id)
223
+ if (request === undefined) return
224
+
225
+ stream = request._responseStream
226
+ } else {
227
+ return
228
+ }
229
+
230
+ stream.cork()
231
+ }
232
+
233
+ _onstreamresume (message) {
234
+ let stream
235
+
236
+ if (message.stream & s.REQUEST) {
237
+ const request = this._requests.get(message.id)
238
+ if (request === undefined) return
239
+
240
+ stream = request._requestStream
241
+ } else if (message.stream & s.RESPONSE) {
242
+ const request = this._responses.get(message.id)
243
+ if (request === undefined) return
244
+
245
+ stream = request._responseStream
246
+ } else {
247
+ return
122
248
  }
249
+
250
+ stream.uncork()
251
+ }
252
+
253
+ _onstreamdata (message) {
254
+ const request = this._incoming.get(message.id)
255
+ if (request === undefined) return
256
+
257
+ let stream
258
+
259
+ if (message.stream & s.REQUEST) {
260
+ stream = request._requestStream
261
+ } else if (message.stream & s.RESPONSE) {
262
+ stream = request._responseStream
263
+ } else {
264
+ return
265
+ }
266
+
267
+ if (stream.push(message.data) === false) {
268
+ this._sendMessage({
269
+ type: t.STREAM,
270
+ id: stream._request.id,
271
+ stream: stream._mask | s.PAUSE,
272
+ error: null,
273
+ data: null
274
+ })
275
+ }
276
+ }
277
+
278
+ _onstreamend (message) {
279
+ const request = this._incoming.get(message.id)
280
+ if (request === undefined) return
281
+
282
+ let stream
283
+
284
+ if (message.stream & s.REQUEST) {
285
+ stream = request._requestStream
286
+ } else if (message.stream & s.RESPONSE) {
287
+ stream = request._responseStream
288
+ } else {
289
+ return
290
+ }
291
+
292
+ stream.push(null)
293
+ }
294
+
295
+ _onstreamdestroy (message) {
296
+ let stream
297
+
298
+ if (message.stream & s.REQUEST) {
299
+ const request = this._requests.get(message.id)
300
+ if (request === undefined) return
301
+
302
+ stream = request._requestStream
303
+ } else if (message.stream & s.RESPONSE) {
304
+ const request = this._responses.get(message.id)
305
+ if (request === undefined) return
306
+
307
+ stream = request._responseStream
308
+ } else {
309
+ return
310
+ }
311
+
312
+ stream.destroy(message.error)
123
313
  }
124
314
  }
package/lib/constants.js CHANGED
@@ -1,6 +1,19 @@
1
1
  module.exports = {
2
2
  type: {
3
3
  REQUEST: 1,
4
- RESPONSE: 2
4
+ RESPONSE: 2,
5
+ STREAM: 3
6
+ },
7
+ stream: {
8
+ OPEN: 0x1,
9
+ CLOSE: 0x2,
10
+ PAUSE: 0x4,
11
+ RESUME: 0x8,
12
+ DATA: 0x10,
13
+ END: 0x20,
14
+ DESTROY: 0x40,
15
+ ERROR: 0x80,
16
+ REQUEST: 0x100,
17
+ RESPONSE: 0x200
5
18
  }
6
19
  }
@@ -1,12 +1,33 @@
1
+ const errors = require('./errors')
2
+
1
3
  module.exports = class RPCIncomingRequest {
2
4
  constructor (rpc, id, command, data) {
3
5
  this.rpc = rpc
4
6
  this.id = id
5
7
  this.command = command
6
8
  this.data = data
9
+ this.sent = false
10
+
11
+ this._requestStream = null
12
+ this._responseStream = null
7
13
  }
8
14
 
9
15
  reply (data) {
10
- return this.rpc._reply(this, typeof data === 'string' ? Buffer.from(data) : data)
16
+ if (this.sent) throw errors.ALREADY_SENT('Response has already been sent')
17
+ this.sent = true
18
+
19
+ this.rpc._sendResponse(this, typeof data === 'string' ? Buffer.from(data) : data)
20
+ }
21
+
22
+ createResponseStream (opts = {}) {
23
+ if (this._responseStream === null) this.rpc._createResponseStream(this, true, opts)
24
+
25
+ return this._responseStream
26
+ }
27
+
28
+ createRequestStream (opts = {}) {
29
+ if (this._requestStream === null) this.rpc._createRequestStream(this, false, opts)
30
+
31
+ return this._requestStream
11
32
  }
12
33
  }
@@ -0,0 +1,59 @@
1
+ const { Readable } = require('bare-stream')
2
+ const { type: t, stream: s } = require('./constants')
3
+
4
+ module.exports = class RPCIncomingStream extends Readable {
5
+ constructor (rpc, request, type, opts) {
6
+ super({ ...opts, eagerOpen: true })
7
+
8
+ this._rpc = rpc
9
+ this._request = request
10
+ this._type = type
11
+ this._mask = type === t.REQUEST ? s.REQUEST : s.RESPONSE
12
+
13
+ this._pendingOpen = null
14
+ }
15
+
16
+ _open (cb) {
17
+ this._rpc._sendMessage({
18
+ type: t.STREAM,
19
+ id: this._request.id,
20
+ stream: this._mask | s.OPEN,
21
+ error: null,
22
+ data: null
23
+ })
24
+
25
+ cb(null)
26
+ }
27
+
28
+ _read () {
29
+ this._rpc._sendMessage({
30
+ type: t.STREAM,
31
+ id: this._request.id,
32
+ stream: this._mask | s.RESUME,
33
+ error: null,
34
+ data: null
35
+ })
36
+ }
37
+
38
+ _destroy (err, cb) {
39
+ if (err) {
40
+ this._rpc._sendMessage({
41
+ type: t.STREAM,
42
+ id: this._request.id,
43
+ stream: this._mask | s.DESTROY | s.ERROR,
44
+ error: err,
45
+ data: null
46
+ })
47
+ } else {
48
+ this._rpc._sendMessage({
49
+ type: t.STREAM,
50
+ id: this._request.id,
51
+ stream: this._mask | s.DESTROY,
52
+ error: null,
53
+ data: null
54
+ })
55
+ }
56
+
57
+ cb(null)
58
+ }
59
+ }
package/lib/messages.js CHANGED
@@ -1,74 +1,92 @@
1
1
  const c = require('compact-encoding')
2
- const { type: t } = require('./constants')
2
+ const { type: t, stream: s } = require('./constants')
3
3
  const errors = require('./errors')
4
4
 
5
5
  const request = {
6
6
  preencode (state, m) {
7
7
  c.utf8.preencode(state, m.command)
8
- c.buffer.preencode(state, m.data)
9
- c.uint.preencode(state, 0) // Reserved
8
+ c.uint.preencode(state, m.stream)
9
+ if (m.stream === 0) c.buffer.preencode(state, m.data)
10
10
  },
11
11
  encode (state, m) {
12
12
  c.utf8.encode(state, m.command)
13
- c.buffer.encode(state, m.data)
14
- c.uint.encode(state, 0) // Reserved
13
+ c.uint.encode(state, m.stream)
14
+ if (m.stream === 0) c.buffer.encode(state, m.data)
15
15
  },
16
16
  decode (state, id) {
17
17
  const command = c.utf8.decode(state)
18
- const data = c.buffer.decode(state)
19
- c.uint.decode(state)
18
+ const stream = c.uint.decode(state)
19
+ const data = stream === 0 ? c.buffer.decode(state) : null
20
20
 
21
- return { type: t.REQUEST, id, command, data }
21
+ return { type: t.REQUEST, id, command, stream, data }
22
22
  }
23
23
  }
24
24
 
25
25
  const error = {
26
26
  preencode (state, m) {
27
27
  c.utf8.preencode(state, m.message)
28
- c.utf8.preencode(state, m.code)
29
- c.int.preencode(state, m.status)
28
+ c.utf8.preencode(state, m.code || '')
29
+ c.int.preencode(state, m.errno || 0)
30
30
  },
31
31
  encode (state, m) {
32
32
  c.utf8.encode(state, m.message)
33
- c.utf8.encode(state, m.code)
34
- c.int.encode(state, m.status)
33
+ c.utf8.encode(state, m.code || '')
34
+ c.int.encode(state, m.errno || 0)
35
35
  },
36
36
  decode (state) {
37
- return {
38
- message: c.utf8.decode(state),
39
- code: c.utf8.decode(state),
40
- status: c.int.decode(state)
41
- }
37
+ const err = new Error(`${c.utf8.decode(state)}`)
38
+ err.code = c.utf8.decode(state)
39
+ err.errno = c.int.decode(state)
40
+ return err
42
41
  }
43
42
  }
44
43
 
45
44
  const response = {
46
45
  preencode (state, m) {
47
- c.bool.preencode(state, m.error)
48
-
49
- if (m.error) error.preencode(state, m)
50
- else c.buffer.preencode(state, m.data)
46
+ c.bool.preencode(state, !!m.error)
47
+ c.uint.preencode(state, m.stream)
51
48
 
52
- c.uint.preencode(state, 0) // Reserved
49
+ if (m.error) error.preencode(state, m.error)
50
+ else if (m.stream === 0) c.buffer.preencode(state, m.data)
53
51
  },
54
52
  encode (state, m) {
55
- c.bool.encode(state, m.error)
53
+ c.bool.encode(state, !!m.error)
54
+ c.uint.encode(state, m.stream)
56
55
 
57
56
  if (m.error) error.encode(state, m)
58
- else c.buffer.encode(state, m.data)
59
-
60
- c.uint.encode(state, 0) // Reserved
57
+ else if (m.stream === 0) c.buffer.encode(state, m.data)
61
58
  },
62
59
  decode (state) {
63
60
  const error = c.bool.decode(state)
61
+ const stream = c.uint.decode(state)
62
+
63
+ if (error) return { stream, error: error.decode(state), data: null }
64
+ if (stream === 0) return { stream, error: null, data: c.buffer.decode(state) }
65
+
66
+ return { stream, error: null, data: null }
67
+ }
68
+ }
69
+
70
+ const stream = {
71
+ preencode (state, m) {
72
+ c.uint.preencode(state, m.stream)
64
73
 
65
- let response
66
- if (error) response = error.decode(state)
67
- else response = { data: c.buffer.decode(state) }
74
+ if (m.stream & s.ERROR) error.preencode(state, m.error)
75
+ else if (m.stream & s.DATA) c.buffer.preencode(state, m.data)
76
+ },
77
+ encode (state, m) {
78
+ c.uint.encode(state, m.stream)
79
+
80
+ if (m.stream & s.ERROR) error.encode(state, m.error)
81
+ else if (m.stream & s.DATA) c.buffer.encode(state, m.data)
82
+ },
83
+ decode (state) {
84
+ const stream = c.uint.decode(state)
68
85
 
69
- c.uint.decode(state)
86
+ if (stream & s.ERROR) return { stream, error: error.decode(state), data: null }
87
+ if (stream & s.DATA) return { stream, error: null, data: c.buffer.decode(state) }
70
88
 
71
- return { error, ...response }
89
+ return { stream, error: null, data: null }
72
90
  }
73
91
  }
74
92
 
@@ -84,6 +102,10 @@ exports.message = {
84
102
  break
85
103
  case t.RESPONSE:
86
104
  response.preencode(state, m)
105
+ break
106
+ case t.STREAM:
107
+ stream.preencode(state, m)
108
+ break
87
109
  }
88
110
  },
89
111
  encode (state, m) {
@@ -102,6 +124,10 @@ exports.message = {
102
124
  break
103
125
  case t.RESPONSE:
104
126
  response.encode(state, m)
127
+ break
128
+ case t.STREAM:
129
+ stream.encode(state, m)
130
+ break
105
131
  }
106
132
 
107
133
  const end = state.start
@@ -124,9 +150,11 @@ exports.message = {
124
150
 
125
151
  switch (type) {
126
152
  case t.REQUEST:
127
- return { type: t.REQUEST, id, ...request.decode(state, id) }
153
+ return { type, id, ...request.decode(state, id) }
128
154
  case t.RESPONSE:
129
- return { type: t.RESPONSE, id, ...response.decode(state, id) }
155
+ return { type, id, ...response.decode(state, id) }
156
+ case t.STREAM:
157
+ return { type, id, ...stream.decode(state, id) }
130
158
  default:
131
159
  throw errors.UNKNOWN_MESSAGE(`Unknown message '${type}'`)
132
160
  }
@@ -3,27 +3,40 @@ const errors = require('./errors')
3
3
  module.exports = class RPCOutgoingRequest {
4
4
  constructor (rpc, command) {
5
5
  this.rpc = rpc
6
+ this.id = -1
6
7
  this.command = command
7
8
  this.sent = false
8
9
 
9
- this._resolve = null
10
- this._reject = null
11
- this._promise = null
10
+ const { promise, resolve, reject } = Promise.withResolvers()
11
+
12
+ this._promise = promise
13
+ this._resolve = resolve
14
+ this._reject = reject
15
+
16
+ this._requestStream = null
17
+ this._responseStream = null
12
18
  }
13
19
 
14
20
  send (data) {
15
- if (this.sent) throw errors.ALREADY_SENT('Response has already been sent')
21
+ if (this.sent) throw errors.ALREADY_SENT('Request has already been sent')
16
22
  this.sent = true
17
23
 
18
- this._promise = new Promise((resolve, reject) => {
19
- this._resolve = resolve
20
- this._reject = reject
21
- })
22
-
23
- return this.rpc._send(this, typeof data === 'string' ? Buffer.from(data) : data)
24
+ this.rpc._sendRequest(this, typeof data === 'string' ? Buffer.from(data) : data)
24
25
  }
25
26
 
26
27
  reply () {
27
28
  return this._promise
28
29
  }
30
+
31
+ createRequestStream (opts = {}) {
32
+ if (this._requestStream === null) this.rpc._createRequestStream(this, true, opts)
33
+
34
+ return this._requestStream
35
+ }
36
+
37
+ createResponseStream (opts = {}) {
38
+ if (this._requestStream === null) this.rpc._createResponseStream(this, false, opts)
39
+
40
+ return this._responseStream
41
+ }
29
42
  }
@@ -0,0 +1,94 @@
1
+ const { Writable } = require('bare-stream')
2
+ const { type: t, stream: s } = require('./constants')
3
+
4
+ module.exports = class RPCOutgoingStream extends Writable {
5
+ constructor (rpc, request, type, opts) {
6
+ super({ ...opts, eagerOpen: true })
7
+
8
+ this._rpc = rpc
9
+ this._request = request
10
+ this._type = type
11
+ this._mask = type === t.REQUEST ? s.REQUEST : s.RESPONSE
12
+
13
+ this._pendingOpen = null
14
+ }
15
+
16
+ _open (cb) {
17
+ this._pendingOpen = cb
18
+
19
+ switch (this._type) {
20
+ case t.REQUEST:
21
+ this._rpc._sendMessage({
22
+ type: t.REQUEST,
23
+ id: this._request.id,
24
+ command: this._request.command,
25
+ stream: s.OPEN,
26
+ data: null
27
+ })
28
+ break
29
+
30
+ case t.RESPONSE:
31
+ this._rpc._sendMessage({
32
+ type: t.RESPONSE,
33
+ id: this._request.id,
34
+ error: false,
35
+ stream: s.OPEN,
36
+ data: null
37
+ })
38
+ break
39
+ }
40
+ }
41
+
42
+ _continueOpen () {
43
+ if (this._pendingOpen === null) return
44
+ const cb = this._pendingOpen
45
+ this._pendingOpen = null
46
+ cb()
47
+ }
48
+
49
+ _write (data, encoding, cb) {
50
+ this._rpc._sendMessage({
51
+ type: t.STREAM,
52
+ id: this._request.id,
53
+ stream: this._mask | s.DATA,
54
+ error: null,
55
+ data
56
+ })
57
+
58
+ cb(null)
59
+ }
60
+
61
+ _final (cb) {
62
+ this._rpc._sendMessage({
63
+ type: t.STREAM,
64
+ id: this._request.id,
65
+ stream: this._mask | s.END,
66
+ error: null,
67
+ data: null
68
+ })
69
+
70
+ cb(null)
71
+ }
72
+
73
+ _destroy (err, cb) {
74
+ if (err) {
75
+ this._rpc._sendMessage({
76
+ type: t.STREAM,
77
+ id: this._request.id,
78
+ stream: this._mask | s.CLOSE | s.ERROR,
79
+ error: err,
80
+ data: null
81
+ })
82
+ } else {
83
+ this._rpc._sendMessage({
84
+ type: t.STREAM,
85
+ id: this._request.id,
86
+ stream: this._mask | s.CLOSE,
87
+ error: null,
88
+ data: null
89
+ })
90
+ }
91
+
92
+ cb(null)
93
+ }
94
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-rpc",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "librpc ABI compatible RPC for Bare",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -24,12 +24,15 @@
24
24
  "url": "https://github.com/holepunchto/bare-rpc/issues"
25
25
  },
26
26
  "homepage": "https://github.com/holepunchto/bare-rpc#readme",
27
+ "engines": {
28
+ "bare": ">=1.4.0"
29
+ },
27
30
  "dependencies": {
31
+ "bare-stream": "^2.1.3",
28
32
  "compact-encoding": "^2.15.0",
29
33
  "safety-catch": "^1.0.2"
30
34
  },
31
35
  "devDependencies": {
32
- "bare-stream": "^2.1.3",
33
36
  "brittle": "^3.2.1",
34
37
  "standard": "^17.0.0"
35
38
  }