Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: listLocalPeers() & local-peers event #360

Merged
merged 14 commits into from
Nov 9, 2023
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)
}
Comment on lines +481 to +483
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't feel like this strictly needs to be async but i have this sentiment elsewhere in the codebase, so not worth changing 😄

}

// 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
}
)
}
Loading