Skip to content

Commit

Permalink
feat: listLocalPeers() & local-peers event (#360)
Browse files Browse the repository at this point in the history
* WIP initial work

* rename Rpc to LocalPeers

* Handle deviceInfo internally, id -> deviceId

* Tests for stream error handling

* remove unnecessary constructor

* return replication stream

* Attach protomux instance to peer info

* rename and re-organize

* revert changes outside scope of PR

* WIP initial work

* Tie everything together

* rename getProjectInstance

* feat: client.listLocalPeers() & `local-peers` evt
  • Loading branch information
gmaclennan authored Nov 9, 2023
1 parent a32cab0 commit ab77e51
Showing 1 changed file with 51 additions and 1 deletion.
52 changes: 51 additions & 1 deletion src/mapeo-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { RandomAccessFilePool } from './core-manager/random-access-file-pool.js'
import { LocalPeers } from './local-peers.js'
import { InviteApi } from './invite-api.js'
import { LocalDiscovery } from './discovery/local-discovery.js'
import { TypedEmitter } from 'tiny-typed-emitter'

/** @typedef {import("@mapeo/schema").ProjectSettingsValue} ProjectValue */

Expand All @@ -40,7 +41,19 @@ const MAX_FILE_DESCRIPTORS = 768

export const kRPC = Symbol('rpc')

export class MapeoManager {
/**
* @typedef {Omit<import('./local-peers.js').PeerInfo, 'protomux'>} PublicPeerInfo
*/

/**
* @typedef {object} MapeoManagerEvents
* @property {(peers: PublicPeerInfo[]) => void} local-peers Emitted when the list of connected peers changes (new ones added, or connection status changes)
*/

/**
* @extends {TypedEmitter<MapeoManagerEvents>}
*/
export class MapeoManager extends TypedEmitter {
#keyManager
#projectSettingsIndexWriter
#db
Expand All @@ -62,6 +75,7 @@ export class MapeoManager {
* @param {string | import('./types.js').CoreStorage} opts.coreStorage Folder for hypercore storage or a function that returns a RandomAccessStorage instance
*/
constructor({ rootKey, dbFolder, coreStorage }) {
super()
this.#dbFolder = dbFolder
const sqlite = new Database(
dbFolder === ':memory:'
Expand All @@ -74,6 +88,10 @@ export class MapeoManager {
})

this.#localPeers = new LocalPeers()
this.#localPeers.on('peers', (peers) => {
this.emit('local-peers', omitPeerProtomux(peers))
})

this.#keyManager = new KeyManager(rootKey)
this.#deviceId = getDeviceId(this.#keyManager)
this.#projectSettingsIndexWriter = new IndexWriter({
Expand Down Expand Up @@ -456,4 +474,36 @@ export class MapeoManager {
get invite() {
return this.#invite
}

/**
* @returns {Promise<PublicPeerInfo[]>}
*/
async listLocalPeers() {
return omitPeerProtomux(this.#localPeers.peers)
}
}

// We use the `protomux` property of connected peers internally, but we don't
// expose it to the API. I have avoided using a private symbol for this for fear
// that we could accidentally keep references around of protomux instances,
// which could cause a memory leak (it shouldn't, but just to eliminate the
// possibility)

/**
* Remove the protomux property of connected peers
*
* @param {import('./local-peers.js').PeerInfo[]} peers
* @returns {PublicPeerInfo[]}
*/
function omitPeerProtomux(peers) {
return peers.map(
({
// @ts-ignore
// eslint-disable-next-line no-unused-vars
protomux,
...publicPeerInfo
}) => {
return publicPeerInfo
}
)
}

0 comments on commit ab77e51

Please sign in to comment.