@libp2p/devtools-metrics 0.1.1 → 0.2.0-15eb66428

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 (58) hide show
  1. package/dist/index.min.js +1 -1
  2. package/dist/src/index.d.ts +25 -96
  3. package/dist/src/index.d.ts.map +1 -1
  4. package/dist/src/index.js +71 -132
  5. package/dist/src/index.js.map +1 -1
  6. package/dist/src/rpc/codecs/cid.d.ts +4 -0
  7. package/dist/src/rpc/codecs/cid.d.ts.map +1 -0
  8. package/dist/src/rpc/codecs/cid.js +8 -0
  9. package/dist/src/rpc/codecs/cid.js.map +1 -0
  10. package/dist/src/rpc/codecs/custom-progress-event.d.ts +4 -0
  11. package/dist/src/rpc/codecs/custom-progress-event.d.ts.map +1 -0
  12. package/dist/src/rpc/codecs/custom-progress-event.js +15 -0
  13. package/dist/src/rpc/codecs/custom-progress-event.js.map +1 -0
  14. package/dist/src/rpc/codecs/multiaddr.d.ts +4 -0
  15. package/dist/src/rpc/codecs/multiaddr.d.ts.map +1 -0
  16. package/dist/src/rpc/codecs/multiaddr.js +8 -0
  17. package/dist/src/rpc/codecs/multiaddr.js.map +1 -0
  18. package/dist/src/rpc/codecs/peer-id.d.ts +4 -0
  19. package/dist/src/rpc/codecs/peer-id.d.ts.map +1 -0
  20. package/dist/src/rpc/codecs/peer-id.js +9 -0
  21. package/dist/src/rpc/codecs/peer-id.js.map +1 -0
  22. package/dist/src/rpc/index.d.ts +99 -0
  23. package/dist/src/rpc/index.d.ts.map +1 -0
  24. package/dist/src/rpc/index.js +11 -0
  25. package/dist/src/rpc/index.js.map +1 -0
  26. package/dist/src/rpc/rpc.d.ts +4 -0
  27. package/dist/src/rpc/rpc.d.ts.map +1 -0
  28. package/dist/src/rpc/rpc.js +51 -0
  29. package/dist/src/rpc/rpc.js.map +1 -0
  30. package/dist/src/utils/debounce.d.ts +2 -0
  31. package/dist/src/utils/debounce.d.ts.map +1 -0
  32. package/dist/src/utils/debounce.js +21 -0
  33. package/dist/src/utils/debounce.js.map +1 -0
  34. package/dist/src/utils/get-peers.d.ts +9 -0
  35. package/dist/src/utils/get-peers.d.ts.map +1 -0
  36. package/dist/src/utils/get-peers.js +42 -0
  37. package/dist/src/utils/get-peers.js.map +1 -0
  38. package/dist/src/utils/get-self.d.ts +8 -0
  39. package/dist/src/utils/get-self.d.ts.map +1 -0
  40. package/dist/src/utils/get-self.js +13 -0
  41. package/dist/src/utils/get-self.js.map +1 -0
  42. package/dist/src/utils/to-object.d.ts +2 -0
  43. package/dist/src/utils/to-object.d.ts.map +1 -0
  44. package/dist/src/utils/to-object.js +8 -0
  45. package/dist/src/utils/to-object.js.map +1 -0
  46. package/package.json +34 -8
  47. package/src/index.ts +109 -259
  48. package/src/rpc/codecs/cid.ts +9 -0
  49. package/src/rpc/codecs/custom-progress-event.ts +17 -0
  50. package/src/rpc/codecs/multiaddr.ts +10 -0
  51. package/src/rpc/codecs/peer-id.ts +11 -0
  52. package/src/rpc/index.ts +122 -0
  53. package/src/rpc/rpc.ts +59 -0
  54. package/src/utils/debounce.ts +23 -0
  55. package/src/utils/get-peers.ts +53 -0
  56. package/src/utils/get-self.ts +21 -0
  57. package/src/utils/to-object.ts +9 -0
  58. package/dist/typedoc-urls.json +0 -46
@@ -0,0 +1,42 @@
1
+ import { base64 } from 'multiformats/bases/base64';
2
+ import { toObject } from './to-object.js';
3
+ export async function getPeers(components, log) {
4
+ const peers = [];
5
+ const connections = components.connectionManager.getConnectionsMap();
6
+ const connectedAddresses = [...connections.values()].flatMap(conn => conn).map(conn => conn.remoteAddr.toString());
7
+ for (const [peerId, conns] of connections.entries()) {
8
+ try {
9
+ const peer = await components.peerStore.get(peerId);
10
+ peers.push({
11
+ id: peerId,
12
+ addresses: peer.addresses.map(({ isCertified, multiaddr }) => {
13
+ return {
14
+ multiaddr,
15
+ isCertified,
16
+ isConnected: connectedAddresses.includes(multiaddr.toString())
17
+ };
18
+ }),
19
+ protocols: [...peer.protocols],
20
+ tags: toObject(peer.tags, (t) => t.value),
21
+ metadata: toObject(peer.metadata, (buf) => base64.encode(buf))
22
+ });
23
+ }
24
+ catch (err) {
25
+ log.error('could not load peer data from peer store', err);
26
+ peers.push({
27
+ id: peerId,
28
+ addresses: conns.map(conn => {
29
+ return {
30
+ multiaddr: conn.remoteAddr,
31
+ isConnected: connectedAddresses.includes(conn.remoteAddr.toString())
32
+ };
33
+ }),
34
+ protocols: [],
35
+ tags: {},
36
+ metadata: {}
37
+ });
38
+ }
39
+ }
40
+ return peers;
41
+ }
42
+ //# sourceMappingURL=get-peers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-peers.js","sourceRoot":"","sources":["../../../src/utils/get-peers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAUzC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAE,UAAsB,EAAE,GAAW;IACjE,MAAM,KAAK,GAAW,EAAE,CAAA;IACxB,MAAM,WAAW,GAAG,UAAU,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,CAAA;IACpE,MAAM,kBAAkB,GAAG,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAA;IAElH,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YAEnD,KAAK,CAAC,IAAI,CAAC;gBACT,EAAE,EAAE,MAAM;gBACV,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,EAAE;oBAC3D,OAAO;wBACL,SAAS;wBACT,WAAW;wBACX,WAAW,EAAE,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;qBAC/D,CAAA;gBACH,CAAC,CAAC;gBACF,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;gBAC9B,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;gBACzC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;aAC/D,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,KAAK,CAAC,0CAA0C,EAAE,GAAG,CAAC,CAAA;YAE1D,KAAK,CAAC,IAAI,CAAC;gBACT,EAAE,EAAE,MAAM;gBACV,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;oBAC1B,OAAO;wBACL,SAAS,EAAE,IAAI,CAAC,UAAU;wBAC1B,WAAW,EAAE,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;qBACrE,CAAA;gBACH,CAAC,CAAC;gBACF,SAAS,EAAE,EAAE;gBACb,IAAI,EAAE,EAAE;gBACR,QAAQ,EAAE,EAAE;aACb,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Peer } from '../rpc/index.js';
2
+ import type { PeerId, PeerStore } from '@libp2p/interface';
3
+ export interface Components {
4
+ peerId: PeerId;
5
+ peerStore: PeerStore;
6
+ }
7
+ export declare function getSelf(components: Components): Promise<Peer>;
8
+ //# sourceMappingURL=get-self.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-self.d.ts","sourceRoot":"","sources":["../../../src/utils/get-self.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAE1D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,wBAAsB,OAAO,CAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAUpE"}
@@ -0,0 +1,13 @@
1
+ import { base64 } from 'multiformats/bases/base64';
2
+ import { toObject } from './to-object.js';
3
+ export async function getSelf(components) {
4
+ const peer = await components.peerStore.get(components.peerId);
5
+ return {
6
+ id: peer.id,
7
+ addresses: peer.addresses,
8
+ protocols: [...peer.protocols],
9
+ tags: toObject(peer.tags, (t) => t.value),
10
+ metadata: toObject(peer.metadata, (buf) => base64.encode(buf))
11
+ };
12
+ }
13
+ //# sourceMappingURL=get-self.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-self.js","sourceRoot":"","sources":["../../../src/utils/get-self.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AASzC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAE,UAAsB;IACnD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IAE9D,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;QAC9B,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QACzC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;KAC/D,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function toObject<T, R>(map: Map<string, T>, transform: (value: T) => R): Record<string, R>;
2
+ //# sourceMappingURL=to-object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-object.d.ts","sourceRoot":"","sources":["../../../src/utils/to-object.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAE,CAAC,EAAE,CAAC,EAAG,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAQnG"}
@@ -0,0 +1,8 @@
1
+ export function toObject(map, transform) {
2
+ const output = {};
3
+ for (const [key, value] of map.entries()) {
4
+ output[key] = transform(value);
5
+ }
6
+ return output;
7
+ }
8
+ //# sourceMappingURL=to-object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-object.js","sourceRoot":"","sources":["../../../src/utils/to-object.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAS,GAAmB,EAAE,SAA0B;IAC9E,MAAM,MAAM,GAAwB,EAAE,CAAA;IAEtC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;IAChC,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libp2p/devtools-metrics",
3
- "version": "0.1.1",
3
+ "version": "0.2.0-15eb66428",
4
4
  "description": "Collect libp2p metrics and send them to browser DevTools",
5
5
  "author": "",
6
6
  "license": "Apache-2.0 OR MIT",
@@ -18,6 +18,22 @@
18
18
  },
19
19
  "type": "module",
20
20
  "types": "./dist/src/index.d.ts",
21
+ "typesVersions": {
22
+ "*": {
23
+ "*": [
24
+ "*",
25
+ "dist/*",
26
+ "dist/src/*",
27
+ "dist/src/*/index"
28
+ ],
29
+ "src/*": [
30
+ "*",
31
+ "dist/*",
32
+ "dist/src/*",
33
+ "dist/src/*/index"
34
+ ]
35
+ }
36
+ },
21
37
  "files": [
22
38
  "src",
23
39
  "dist",
@@ -28,6 +44,10 @@
28
44
  ".": {
29
45
  "types": "./dist/src/index.d.ts",
30
46
  "import": "./dist/src/index.js"
47
+ },
48
+ "./rpc": {
49
+ "types": "./dist/src/rpc/index.d.ts",
50
+ "import": "./dist/src/rpc/index.js"
31
51
  }
32
52
  },
33
53
  "eslintConfig": {
@@ -47,16 +67,22 @@
47
67
  "test:chrome": "aegir test -t browser --cov"
48
68
  },
49
69
  "dependencies": {
50
- "@libp2p/interface": "^1.4.1",
51
- "@libp2p/interface-internal": "^1.2.3",
52
- "@libp2p/logger": "^4.0.14",
53
- "@libp2p/simple-metrics": "^1.0.3",
54
- "multiformats": "^13.1.0"
70
+ "@libp2p/interface": "1.5.0-15eb66428",
71
+ "@libp2p/interface-internal": "1.2.4-15eb66428",
72
+ "@libp2p/logger": "4.0.15-15eb66428",
73
+ "@libp2p/peer-id": "4.1.4-15eb66428",
74
+ "@libp2p/simple-metrics": "1.1.0-15eb66428",
75
+ "@multiformats/multiaddr": "^12.3.0",
76
+ "cborg": "^4.2.2",
77
+ "it-pipe": "^3.0.1",
78
+ "it-pushable": "^3.2.3",
79
+ "it-rpc": "^1.0.0",
80
+ "multiformats": "^13.1.0",
81
+ "progress-events": "^1.0.0"
55
82
  },
56
83
  "devDependencies": {
57
- "@libp2p/peer-id-factory": "^4.1.3",
84
+ "@libp2p/peer-id-factory": "4.1.4-15eb66428",
58
85
  "aegir": "^43.0.1",
59
- "race-event": "^1.3.0",
60
86
  "sinon-ts": "^2.0.0"
61
87
  },
62
88
  "sideEffects": false
package/src/index.ts CHANGED
@@ -16,12 +16,23 @@
16
16
  * for Chrome or Firefox to inspect the state of your running node.
17
17
  */
18
18
 
19
- import { start, stop } from '@libp2p/interface'
20
- import { enable, disable } from '@libp2p/logger'
19
+ import { serviceCapabilities, start, stop } from '@libp2p/interface'
21
20
  import { simpleMetrics } from '@libp2p/simple-metrics'
21
+ import { pipe } from 'it-pipe'
22
+ import { pushable } from 'it-pushable'
23
+ import { rpc, type RPC } from 'it-rpc'
22
24
  import { base64 } from 'multiformats/bases/base64'
23
- import type { ComponentLogger, Connection, Libp2pEvents, Logger, Metrics, MultiaddrConnection, PeerId, Peer as PeerStorePeer, PeerStore, PeerUpdate, Stream, TypedEventEmitter } from '@libp2p/interface'
24
- import type { TransportManager, Registrar, ConnectionManager } from '@libp2p/interface-internal'
25
+ import { valueCodecs } from './rpc/index.js'
26
+ import { metricsRpc } from './rpc/rpc.js'
27
+ import { debounce } from './utils/debounce.js'
28
+ import { getPeers } from './utils/get-peers.js'
29
+ import { getSelf } from './utils/get-self.js'
30
+ import type { DevToolsRPC } from './rpc/index.js'
31
+ import type { ComponentLogger, Connection, Libp2pEvents, Logger, Metrics, MultiaddrConnection, PeerId, PeerStore, Stream, ContentRouting, PeerRouting, TypedEventTarget, Startable } from '@libp2p/interface'
32
+ import type { TransportManager, Registrar, ConnectionManager, AddressManager } from '@libp2p/interface-internal'
33
+ import type { Pushable } from 'it-pushable'
34
+
35
+ export * from './rpc/index.js'
25
36
 
26
37
  export const SOURCE_DEVTOOLS = '@libp2p/devtools-metrics:devtools'
27
38
  export const SOURCE_SERVICE_WORKER = '@libp2p/devtools-metrics:worker'
@@ -36,39 +47,12 @@ Object.defineProperty(globalThis, LIBP2P_DEVTOOLS_METRICS_KEY, {
36
47
  writable: false
37
48
  })
38
49
 
39
- /**
40
- * Sent when new metrics are available
41
- */
42
- export interface MetricsMessage {
43
- source: typeof SOURCE_METRICS
44
- type: 'metrics'
45
- metrics: Record<string, any>
46
- }
47
-
48
- /**
49
- * This message represents the current state of the libp2p node
50
- */
51
- export interface SelfMessage {
52
- source: typeof SOURCE_METRICS
53
- type: 'self'
54
- peer: SelfPeer
55
- }
56
-
57
- /**
58
- * This message represents the current state of the libp2p node
59
- */
60
- export interface PeersMessage {
61
- source: typeof SOURCE_METRICS
62
- type: 'peers'
63
- peers: Peer[]
64
- }
65
-
66
50
  /**
67
51
  * Sent by the DevTools service worker to the DevTools panel when the inspected
68
52
  * page has finished (re)loading
69
53
  */
70
54
  export interface PageLoadedMessage {
71
- source: '@libp2p/devtools-metrics:devtools'
55
+ source: typeof SOURCE_DEVTOOLS
72
56
  type: 'page-loaded'
73
57
  tabId: number
74
58
  }
@@ -81,47 +65,40 @@ export interface PageLoadedMessage {
81
65
  * not having granted permission for the script to run.
82
66
  */
83
67
  export interface PermissionsErrorMessage {
84
- source: '@libp2p/devtools-metrics:devtools'
68
+ source: typeof SOURCE_DEVTOOLS
85
69
  type: 'permissions-error'
86
70
  tabId: number
87
71
  }
88
72
 
89
73
  /**
90
- * This message is sent by DevTools when no `self` message has been received
74
+ * This event is intercepted by the service worker which injects a content
75
+ * script into the current page which copies the passed value to the clipboard.
91
76
  */
92
- export interface IdentifyMessage {
93
- source: '@libp2p/devtools-metrics:devtools'
94
- type: 'identify'
77
+ export interface CopyToClipboardMessage {
78
+ source: typeof SOURCE_DEVTOOLS
79
+ type: 'copy-to-clipboard'
95
80
  tabId: number
81
+ value: string
96
82
  }
97
83
 
98
84
  /**
99
- * This message is sent by DevTools when no `self` message has been received
85
+ * Invoke a method on the libp2p object
100
86
  */
101
- export interface EnableDebugMessage {
102
- source: '@libp2p/devtools-metrics:devtools'
103
- type: 'debug'
104
- namespace: string
87
+ export interface RPCMessage {
88
+ source: typeof SOURCE_DEVTOOLS | typeof SOURCE_METRICS
89
+ type: 'libp2p-rpc'
105
90
  tabId: number
106
- }
107
91
 
108
- /**
109
- * We cannot use the web extension API to copy text to the cliboard yet as it's
110
- * not supported in Firefox yet, so get the page to do it
111
- *
112
- * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard#writing_to_the_clipboard
113
- */
114
- export interface CopyToClipboardMessage {
115
- source: '@libp2p/devtools-metrics:devtools'
116
- type: 'copy-to-clipboard'
117
- value: string
118
- tabId: number
92
+ /**
93
+ * The RPC message encoded as a multibase string
94
+ */
95
+ message: string
119
96
  }
120
97
 
121
98
  /**
122
99
  * Messages that are sent from the application page to the DevTools panel
123
100
  */
124
- export type ApplicationMessage = MetricsMessage | SelfMessage | PeersMessage
101
+ export type ApplicationMessage = RPCMessage
125
102
 
126
103
  /**
127
104
  * Messages that are sent from the service worker
@@ -131,34 +108,7 @@ export type WorkerMessage = PageLoadedMessage | PermissionsErrorMessage
131
108
  /**
132
109
  * Messages that are sent from the DevTools panel page to the application page
133
110
  */
134
- export type DevToolsMessage = IdentifyMessage | EnableDebugMessage | CopyToClipboardMessage
135
-
136
- export interface SelfPeer {
137
- /**
138
- * The identifier of the peer
139
- */
140
- id: string
141
-
142
- /**
143
- * The list of multiaddrs the peer is listening on
144
- */
145
- multiaddrs: string[]
146
-
147
- /**
148
- * Any peer store tags the peer has
149
- */
150
- tags: Record<string, number>
151
-
152
- /**
153
- * Any peer store metadata the peer has
154
- */
155
- metadata: Record<string, string>
156
-
157
- /**
158
- * The protocols the peer supports
159
- */
160
- protocols: string[]
161
- }
111
+ export type DevToolsMessage = CopyToClipboardMessage | RPCMessage
162
112
 
163
113
  export interface Address {
164
114
  /**
@@ -178,33 +128,6 @@ export interface Address {
178
128
  isConnected?: boolean
179
129
  }
180
130
 
181
- export interface Peer {
182
- /**
183
- * The identifier of the remote peer
184
- */
185
- id: string
186
-
187
- /**
188
- * The list of addresses the peer has that we know about
189
- */
190
- addresses: Address[]
191
-
192
- /**
193
- * Any peer store tags the peer has
194
- */
195
- tags: Record<string, number>
196
-
197
- /**
198
- * Any peer store metadata the peer has
199
- */
200
- metadata: Record<string, string>
201
-
202
- /**
203
- * The protocols the peer supports, if known
204
- */
205
- protocols: string[]
206
- }
207
-
208
131
  export interface DevToolsMetricsInit {
209
132
  /**
210
133
  * How often to pass metrics to the DevTools panel
@@ -214,46 +137,63 @@ export interface DevToolsMetricsInit {
214
137
 
215
138
  export interface DevToolsMetricsComponents {
216
139
  logger: ComponentLogger
217
- events: TypedEventEmitter<Libp2pEvents>
140
+ events: TypedEventTarget<Libp2pEvents>
218
141
  peerId: PeerId
219
142
  transportManager: TransportManager
220
143
  registrar: Registrar
221
144
  connectionManager: ConnectionManager
222
145
  peerStore: PeerStore
146
+
147
+ contentRouting: ContentRouting
148
+ peerRouting: PeerRouting
149
+ addressManager: AddressManager
223
150
  }
224
151
 
225
- class DevToolsMetrics implements Metrics {
152
+ class DevToolsMetrics implements Metrics, Startable {
226
153
  private readonly log: Logger
227
154
  private readonly components: DevToolsMetricsComponents
228
155
  private readonly simpleMetrics: Metrics
229
156
  private readonly intervalMs?: number
157
+ private readonly rpcQueue: Pushable<Uint8Array>
158
+ private readonly rpc: RPC
159
+ private readonly devTools: DevToolsRPC
230
160
 
231
161
  constructor (components: DevToolsMetricsComponents, init?: Partial<DevToolsMetricsInit>) {
232
162
  this.log = components.logger.forComponent('libp2p:devtools-metrics')
233
163
  this.intervalMs = init?.intervalMs
234
164
  this.components = components
235
165
 
166
+ // create RPC endpoint
167
+ this.rpcQueue = pushable()
168
+ this.rpc = rpc({
169
+ valueCodecs
170
+ })
171
+ this.devTools = this.rpc.createClient('devTools')
172
+
236
173
  // collect information on current peers and sent it to the dev tools panel
237
174
  this.onPeersUpdate = debounce(this.onPeersUpdate.bind(this), 1000)
238
- this.onSelfUpdate = this.onSelfUpdate.bind(this)
175
+ this.onSelfUpdate = debounce(this.onSelfUpdate.bind(this), 1000)
239
176
  this.onIncomingMessage = this.onIncomingMessage.bind(this)
240
177
 
241
178
  // collect metrics
242
179
  this.simpleMetrics = simpleMetrics({
243
180
  intervalMs: this.intervalMs,
244
181
  onMetrics: (metrics) => {
245
- const message: MetricsMessage = {
246
- source: SOURCE_METRICS,
247
- type: 'metrics',
248
- metrics
249
- }
250
-
251
- this.log('post metrics message')
252
- window.postMessage(message, '*')
182
+ this.devTools.safeDispatchEvent('metrics', {
183
+ detail: metrics
184
+ }).catch(err => {
185
+ this.log.error('error sending metrics', err)
186
+ })
253
187
  }
254
188
  })({})
255
189
  }
256
190
 
191
+ readonly [Symbol.toStringTag] = '@libp2p/devtools-metrics'
192
+
193
+ readonly [serviceCapabilities]: string[] = [
194
+ '@libp2p/metrics'
195
+ ]
196
+
257
197
  trackMultiaddrConnection (maConn: MultiaddrConnection): void {
258
198
  this.simpleMetrics.trackMultiaddrConnection(maConn)
259
199
  }
@@ -291,8 +231,32 @@ class DevToolsMetrics implements Metrics {
291
231
  // process incoming messages from devtools
292
232
  window.addEventListener('message', this.onIncomingMessage)
293
233
 
234
+ // create rpc target
235
+ this.rpc.createTarget('metrics', metricsRpc(this.components))
236
+
294
237
  // send metrics
295
238
  await start(this.simpleMetrics)
239
+
240
+ // send RPC messages
241
+ Promise.resolve()
242
+ .then(async () => {
243
+ await pipe(
244
+ this.rpcQueue,
245
+ this.rpc,
246
+ async source => {
247
+ for await (const buf of source) {
248
+ window.postMessage({
249
+ source: SOURCE_METRICS,
250
+ type: 'libp2p-rpc',
251
+ message: base64.encode(buf)
252
+ })
253
+ }
254
+ }
255
+ )
256
+ })
257
+ .catch(err => {
258
+ this.log.error('error while reading RPC messages', err)
259
+ })
296
260
  }
297
261
 
298
262
  async stop (): Promise<void> {
@@ -305,90 +269,6 @@ class DevToolsMetrics implements Metrics {
305
269
  await stop(this.simpleMetrics)
306
270
  }
307
271
 
308
- private onPeersUpdate (): void {
309
- Promise.resolve().then(async () => {
310
- const message: PeersMessage = {
311
- source: SOURCE_METRICS,
312
- type: 'peers',
313
- peers: []
314
- }
315
-
316
- const connections = this.components.connectionManager.getConnectionsMap()
317
- const connectedAddresses = [...connections.values()].flatMap(conn => conn).map(conn => conn.remoteAddr.toString())
318
-
319
- for (const [peerId, conns] of connections.entries()) {
320
- try {
321
- const peer = await this.components.peerStore.get(peerId)
322
-
323
- message.peers.push({
324
- id: peerId.toString(),
325
- addresses: peer.addresses.map(({ isCertified, multiaddr }) => {
326
- const addr = multiaddr.toString()
327
-
328
- return {
329
- multiaddr: addr,
330
- isCertified,
331
- isConnected: connectedAddresses.includes(addr)
332
- }
333
- }),
334
- protocols: [...peer.protocols],
335
- tags: toObject(peer.tags, (t) => t.value),
336
- metadata: toObject(peer.metadata, (buf) => base64.encode(buf))
337
- })
338
- } catch (err) {
339
- this.log.error('could not load peer data from peer store', err)
340
-
341
- message.peers.push({
342
- id: peerId.toString(),
343
- addresses: conns.map(conn => {
344
- const addr = conn.remoteAddr.toString()
345
-
346
- return {
347
- multiaddr: addr,
348
- isConnected: connectedAddresses.includes(addr)
349
- }
350
- }),
351
- protocols: [],
352
- tags: {},
353
- metadata: {}
354
- })
355
- }
356
- }
357
-
358
- window.postMessage(message, '*')
359
- })
360
- .catch(err => {
361
- this.log.error('error sending peers message', err)
362
- })
363
- }
364
-
365
- private onSelfUpdate (evt: CustomEvent<PeerUpdate>): void {
366
- this.sendSelfUpdate(evt.detail.peer)
367
- }
368
-
369
- private sendSelfUpdate (peer: PeerStorePeer): void {
370
- Promise.resolve()
371
- .then(async () => {
372
- const message: SelfMessage = {
373
- source: SOURCE_METRICS,
374
- type: 'self',
375
- peer: {
376
- id: peer.id.toString(),
377
- multiaddrs: peer.addresses.map(({ multiaddr }) => multiaddr.toString()),
378
- protocols: [...peer.protocols],
379
- tags: toObject(peer.tags, (t) => t.value),
380
- metadata: toObject(peer.metadata, (buf) => base64.encode(buf))
381
- }
382
- }
383
-
384
- this.log('post node update message')
385
- window.postMessage(message, '*')
386
- })
387
- .catch(err => {
388
- this.log.error('error sending self update', err)
389
- })
390
- }
391
-
392
272
  private onIncomingMessage (event: MessageEvent<DevToolsMessage>): void {
393
273
  // Only accept messages from same frame
394
274
  if (event.source !== window) {
@@ -402,29 +282,33 @@ class DevToolsMetrics implements Metrics {
402
282
  return
403
283
  }
404
284
 
405
- // respond to identify request
406
- if (message.type === 'identify') {
407
- Promise.resolve()
408
- .then(async () => {
409
- const peer = await this.components.peerStore.get(this.components.peerId)
285
+ if (message.type === 'libp2p-rpc') {
286
+ this.rpcQueue.push(base64.decode(message.message))
287
+ }
288
+ }
410
289
 
411
- this.sendSelfUpdate(peer)
412
- // also send our current peer list
413
- this.onPeersUpdate()
414
- })
415
- .catch(err => {
416
- this.log.error('error sending identify response', err)
290
+ private onSelfUpdate (): void {
291
+ Promise.resolve()
292
+ .then(async () => {
293
+ await this.devTools.safeDispatchEvent('self', {
294
+ detail: await getSelf(this.components)
417
295
  })
418
- }
296
+ })
297
+ .catch(err => {
298
+ this.log.error('error sending peers message', err)
299
+ })
300
+ }
419
301
 
420
- // handle enabling/disabling debug namespaces
421
- if (message.type === 'debug') {
422
- if (message.namespace.length > 0) {
423
- enable(message.namespace)
424
- } else {
425
- disable()
426
- }
427
- }
302
+ private onPeersUpdate (): void {
303
+ Promise.resolve()
304
+ .then(async () => {
305
+ await this.devTools.safeDispatchEvent('peers', {
306
+ detail: await getPeers(this.components, this.log)
307
+ })
308
+ })
309
+ .catch(err => {
310
+ this.log.error('error sending peers message', err)
311
+ })
428
312
  }
429
313
  }
430
314
 
@@ -433,37 +317,3 @@ export function devToolsMetrics (init?: Partial<DevToolsMetricsInit>): (componen
433
317
  return new DevToolsMetrics(components, init)
434
318
  }
435
319
  }
436
-
437
- function toObject <T, R> (map: Map<string, T>, transform: (value: T) => R): Record<string, R> {
438
- const output: Record<string, any> = {}
439
-
440
- for (const [key, value] of map.entries()) {
441
- output[key] = transform(value)
442
- }
443
-
444
- return output
445
- }
446
-
447
- function debounce (callback: () => void, wait: number = 100): () => void {
448
- let timeout: ReturnType<typeof setTimeout>
449
- let start: number | undefined
450
-
451
- return (): void => {
452
- if (start == null) {
453
- start = Date.now()
454
- }
455
-
456
- if (timeout != null && Date.now() - start > wait) {
457
- clearTimeout(timeout)
458
- start = undefined
459
- callback()
460
- return
461
- }
462
-
463
- clearTimeout(timeout)
464
- timeout = setTimeout(() => {
465
- start = undefined
466
- callback()
467
- }, wait)
468
- }
469
- }
@@ -0,0 +1,9 @@
1
+ import { CID } from 'multiformats/cid'
2
+ import type { ValueCodec } from 'it-rpc'
3
+
4
+ export const cidCodec: ValueCodec<CID> = {
5
+ type: 4096,
6
+ canEncode: (val) => val.code != null && val.version != null && val.multihash != null && val['/'] != null,
7
+ encode: (val) => val.bytes,
8
+ decode: (buf) => CID.decode(buf)
9
+ }