@libp2p/pubsub 0.0.0 → 1.0.2

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.
Files changed (76) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +35 -0
  3. package/dist/src/errors.d.ts +39 -0
  4. package/dist/src/errors.d.ts.map +1 -0
  5. package/dist/src/errors.js +41 -0
  6. package/dist/src/errors.js.map +1 -0
  7. package/dist/src/index.d.ts +180 -0
  8. package/dist/src/index.d.ts.map +1 -0
  9. package/dist/src/index.js +467 -0
  10. package/dist/src/index.js.map +1 -0
  11. package/dist/src/message/rpc.d.ts +258 -0
  12. package/dist/src/message/rpc.js +699 -0
  13. package/dist/src/message/sign.d.ts +17 -0
  14. package/dist/src/message/sign.d.ts.map +1 -0
  15. package/dist/src/message/sign.js +84 -0
  16. package/dist/src/message/sign.js.map +1 -0
  17. package/dist/src/message/topic-descriptor.d.ts +254 -0
  18. package/dist/src/message/topic-descriptor.js +647 -0
  19. package/dist/src/peer-streams.d.ts +67 -0
  20. package/dist/src/peer-streams.d.ts.map +1 -0
  21. package/dist/src/peer-streams.js +112 -0
  22. package/dist/src/peer-streams.js.map +1 -0
  23. package/dist/src/utils.d.ts +29 -0
  24. package/dist/src/utils.d.ts.map +1 -0
  25. package/dist/src/utils.js +80 -0
  26. package/dist/src/utils.js.map +1 -0
  27. package/dist/test/emit-self.spec.d.ts +2 -0
  28. package/dist/test/emit-self.spec.d.ts.map +1 -0
  29. package/dist/test/emit-self.spec.js +63 -0
  30. package/dist/test/emit-self.spec.js.map +1 -0
  31. package/dist/test/instance.spec.d.ts +2 -0
  32. package/dist/test/instance.spec.d.ts.map +1 -0
  33. package/dist/test/instance.spec.js +50 -0
  34. package/dist/test/instance.spec.js.map +1 -0
  35. package/dist/test/lifesycle.spec.d.ts +2 -0
  36. package/dist/test/lifesycle.spec.d.ts.map +1 -0
  37. package/dist/test/lifesycle.spec.js +192 -0
  38. package/dist/test/lifesycle.spec.js.map +1 -0
  39. package/dist/test/message.spec.d.ts +2 -0
  40. package/dist/test/message.spec.d.ts.map +1 -0
  41. package/dist/test/message.spec.js +83 -0
  42. package/dist/test/message.spec.js.map +1 -0
  43. package/dist/test/pubsub.spec.d.ts +2 -0
  44. package/dist/test/pubsub.spec.d.ts.map +1 -0
  45. package/dist/test/pubsub.spec.js +310 -0
  46. package/dist/test/pubsub.spec.js.map +1 -0
  47. package/dist/test/sign.spec.d.ts +2 -0
  48. package/dist/test/sign.spec.d.ts.map +1 -0
  49. package/dist/test/sign.spec.js +93 -0
  50. package/dist/test/sign.spec.js.map +1 -0
  51. package/dist/test/topic-validators.spec.d.ts +2 -0
  52. package/dist/test/topic-validators.spec.d.ts.map +1 -0
  53. package/dist/test/topic-validators.spec.js +86 -0
  54. package/dist/test/topic-validators.spec.js.map +1 -0
  55. package/dist/test/utils/index.d.ts +23 -0
  56. package/dist/test/utils/index.d.ts.map +1 -0
  57. package/dist/test/utils/index.js +86 -0
  58. package/dist/test/utils/index.js.map +1 -0
  59. package/dist/test/utils.spec.d.ts +2 -0
  60. package/dist/test/utils.spec.d.ts.map +1 -0
  61. package/dist/test/utils.spec.js +53 -0
  62. package/dist/test/utils.spec.js.map +1 -0
  63. package/dist/tsconfig.tsbuildinfo +1 -0
  64. package/package.json +192 -4
  65. package/src/README.md +251 -0
  66. package/src/errors.ts +45 -0
  67. package/src/index.ts +610 -0
  68. package/src/message/rpc.d.ts +258 -0
  69. package/src/message/rpc.js +699 -0
  70. package/src/message/rpc.proto +20 -0
  71. package/src/message/sign.ts +101 -0
  72. package/src/message/topic-descriptor.d.ts +254 -0
  73. package/src/message/topic-descriptor.js +647 -0
  74. package/src/message/topic-descriptor.proto +30 -0
  75. package/src/peer-streams.ts +169 -0
  76. package/src/utils.ts +93 -0
@@ -0,0 +1,169 @@
1
+ import debug from 'debug'
2
+ import { EventEmitter } from 'events'
3
+ import lp from 'it-length-prefixed'
4
+ import pushable from 'it-pushable'
5
+ import { pipe } from 'it-pipe'
6
+ import { source as abortable } from 'abortable-iterator'
7
+ import AbortController from 'abort-controller'
8
+ import type { PeerId } from '@libp2p/interfaces/peer-id'
9
+ import type { MuxedStream } from '@libp2p/interfaces/stream-muxer'
10
+
11
+ const log = Object.assign(debug('libp2p-pubsub:peer-streams'), {
12
+ error: debug('libp2p-pubsub:peer-streams:err')
13
+ })
14
+
15
+ export interface Options {
16
+ id: PeerId
17
+ protocol: string
18
+ }
19
+
20
+ /**
21
+ * Thin wrapper around a peer's inbound / outbound pubsub streams
22
+ */
23
+ export class PeerStreams extends EventEmitter {
24
+ public readonly id: PeerId
25
+ public readonly protocol: string
26
+ /**
27
+ * Write stream - it's preferable to use the write method
28
+ */
29
+ public outboundStream: pushable.Pushable<Uint8Array> | undefined
30
+ /**
31
+ * Read stream
32
+ */
33
+ public inboundStream: AsyncIterable<Uint8Array> | undefined
34
+ /**
35
+ * The raw outbound stream, as retrieved from conn.newStream
36
+ */
37
+ private _rawOutboundStream: MuxedStream | undefined
38
+ /**
39
+ * The raw inbound stream, as retrieved from the callback from libp2p.handle
40
+ */
41
+ private _rawInboundStream: MuxedStream | undefined
42
+ /**
43
+ * An AbortController for controlled shutdown of the inbound stream
44
+ */
45
+ private readonly _inboundAbortController: AbortController
46
+
47
+ constructor (opts: Options) {
48
+ super()
49
+
50
+ this.id = opts.id
51
+ this.protocol = opts.protocol
52
+
53
+ this._inboundAbortController = new AbortController()
54
+ }
55
+
56
+ /**
57
+ * Do we have a connection to read from?
58
+ *
59
+ * @type {boolean}
60
+ */
61
+ get isReadable () {
62
+ return Boolean(this.inboundStream)
63
+ }
64
+
65
+ /**
66
+ * Do we have a connection to write on?
67
+ *
68
+ * @type {boolean}
69
+ */
70
+ get isWritable () {
71
+ return Boolean(this.outboundStream)
72
+ }
73
+
74
+ /**
75
+ * Send a message to this peer.
76
+ * Throws if there is no `stream` to write to available.
77
+ */
78
+ write (data: Uint8Array) {
79
+ if (this.outboundStream == null) {
80
+ const id = this.id.toString()
81
+ throw new Error('No writable connection to ' + id)
82
+ }
83
+
84
+ this.outboundStream.push(data)
85
+ }
86
+
87
+ /**
88
+ * Attach a raw inbound stream and setup a read stream
89
+ */
90
+ attachInboundStream (stream: MuxedStream) {
91
+ // Create and attach a new inbound stream
92
+ // The inbound stream is:
93
+ // - abortable, set to only return on abort, rather than throw
94
+ // - transformed with length-prefix transform
95
+ this._rawInboundStream = stream
96
+ this.inboundStream = abortable(
97
+ pipe(
98
+ this._rawInboundStream,
99
+ lp.decode()
100
+ ),
101
+ this._inboundAbortController.signal,
102
+ { returnOnAbort: true }
103
+ )
104
+
105
+ this.emit('stream:inbound')
106
+ return this.inboundStream
107
+ }
108
+
109
+ /**
110
+ * Attach a raw outbound stream and setup a write stream
111
+ */
112
+ async attachOutboundStream (stream: MuxedStream) {
113
+ // If an outbound stream already exists, gently close it
114
+ const _prevStream = this.outboundStream
115
+ if (this.outboundStream != null) {
116
+ // End the stream without emitting a close event
117
+ await this.outboundStream.end()
118
+ }
119
+
120
+ this._rawOutboundStream = stream
121
+ this.outboundStream = pushable({
122
+ onEnd: (shouldEmit) => {
123
+ // close writable side of the stream
124
+ if ((this._rawOutboundStream?.reset) != null) {
125
+ this._rawOutboundStream.reset()
126
+ }
127
+
128
+ this._rawOutboundStream = undefined
129
+ this.outboundStream = undefined
130
+ if (shouldEmit != null) {
131
+ this.emit('close')
132
+ }
133
+ }
134
+ })
135
+
136
+ pipe(
137
+ this.outboundStream,
138
+ lp.encode(),
139
+ this._rawOutboundStream
140
+ ).catch((err: Error) => {
141
+ log.error(err)
142
+ })
143
+
144
+ // Only emit if the connection is new
145
+ if (_prevStream == null) {
146
+ this.emit('stream:outbound')
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Closes the open connection to peer
152
+ */
153
+ close () {
154
+ // End the outbound stream
155
+ if (this.outboundStream != null) {
156
+ this.outboundStream.end()
157
+ }
158
+ // End the inbound stream
159
+ if (this.inboundStream != null) {
160
+ this._inboundAbortController.abort()
161
+ }
162
+
163
+ this._rawOutboundStream = undefined
164
+ this.outboundStream = undefined
165
+ this._rawInboundStream = undefined
166
+ this.inboundStream = undefined
167
+ this.emit('close')
168
+ }
169
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,93 @@
1
+ import { randomBytes } from 'iso-random-stream'
2
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
3
+ import { PeerId } from '@libp2p/peer-id'
4
+ import { sha256 } from 'multiformats/hashes/sha2'
5
+ import type * as RPC from './message/rpc.js'
6
+ import type { Message } from '@libp2p/interfaces/pubsub'
7
+
8
+ /**
9
+ * Generate a random sequence number
10
+ */
11
+ export const randomSeqno = () => {
12
+ return randomBytes(8)
13
+ }
14
+
15
+ /**
16
+ * Generate a message id, based on the `from` and `seqno`
17
+ */
18
+ export const msgId = (from: Uint8Array | string, seqno: Uint8Array) => {
19
+ let fromBytes
20
+
21
+ if (from instanceof Uint8Array) {
22
+ fromBytes = PeerId.fromBytes(from).multihash.digest
23
+ } else {
24
+ fromBytes = PeerId.fromString(from).multihash.digest
25
+ }
26
+
27
+ const msgId = new Uint8Array(fromBytes.length + seqno.length)
28
+ msgId.set(fromBytes, 0)
29
+ msgId.set(seqno, fromBytes.length)
30
+ return msgId
31
+ }
32
+
33
+ /**
34
+ * Generate a message id, based on message `data`
35
+ */
36
+ export const noSignMsgId = (data: Uint8Array) => sha256.encode(data)
37
+
38
+ /**
39
+ * Check if any member of the first set is also a member
40
+ * of the second set
41
+ */
42
+ export const anyMatch = (a: Set<number> | number[], b: Set<number> | number[]) => {
43
+ let bHas
44
+ if (Array.isArray(b)) {
45
+ bHas = (val: number) => b.includes(val)
46
+ } else {
47
+ bHas = (val: number) => b.has(val)
48
+ }
49
+
50
+ for (const val of a) {
51
+ if (bHas(val)) {
52
+ return true
53
+ }
54
+ }
55
+
56
+ return false
57
+ }
58
+
59
+ /**
60
+ * Make everything an array
61
+ */
62
+ export const ensureArray = function <T> (maybeArray: T | T[]) {
63
+ if (!Array.isArray(maybeArray)) {
64
+ return [maybeArray]
65
+ }
66
+
67
+ return maybeArray
68
+ }
69
+
70
+ /**
71
+ * Ensures `message.from` is base58 encoded
72
+ */
73
+ export const normalizeInRpcMessage = (message: RPC.RPC.IMessage, peerId?: string) => {
74
+ // @ts-expect-error receivedFrom not yet defined
75
+ const m: NormalizedIMessage = Object.assign({}, message)
76
+
77
+ if (peerId != null) {
78
+ m.receivedFrom = peerId
79
+ }
80
+
81
+ return m
82
+ }
83
+
84
+ export const normalizeOutRpcMessage = (message: Message) => {
85
+ const m: Message = Object.assign({}, message)
86
+ if (typeof message.from === 'string') {
87
+ m.from = uint8ArrayFromString(message.from, 'base58btc')
88
+ }
89
+ if (typeof message.data === 'string') {
90
+ m.data = uint8ArrayFromString(message.data)
91
+ }
92
+ return m
93
+ }