diff --git a/src/core-manager/index.js b/src/core-manager/index.js index ee254e3ae..24dd16bda 100644 --- a/src/core-manager/index.js +++ b/src/core-manager/index.js @@ -14,6 +14,8 @@ import { coresTable } from '../schema/project.js' import * as rle from './bitfield-rle.js' import { CoreIndex } from './core-index.js' +/** @typedef {import('../types.js').HypercorePeer} HypercorePeer */ + const WRITER_CORE_PREHAVES_DEBOUNCE_DELAY = 1000 export const kCoreManagerReplicate = Symbol('replicate core manager') @@ -401,7 +403,7 @@ export class CoreManager extends TypedEmitter { /** * @param {ProjectExtension} msg - * @param {any} peer + * @param {HypercorePeer} peer */ #handleProjectMessage({ wantCoreKeys, ...coreKeys }, peer) { const message = ProjectExtension.create() @@ -426,7 +428,7 @@ export class CoreManager extends TypedEmitter { /** * @param {Omit & { namespace: Namespace | 'UNRECOGNIZED' }} msg - * @param {any} peer + * @param {HypercorePeer} peer */ #handleHaveMessage(msg, peer) { const { start, discoveryKey, bitfield, namespace } = msg @@ -444,7 +446,7 @@ export class CoreManager extends TypedEmitter { /** * - * @param {any} peer + * @param {HypercorePeer} peer * @param {Iterable<{ core: Hypercore, namespace: Namespace }>} cores */ async #sendHaves(peer, cores) { @@ -640,7 +642,7 @@ function findPeer(core, publicKey, { timeout = 200 } = {}) { core.on('peer-add', onPeer) - /** @param {any} peer */ + /** @param {HypercorePeer} peer */ function onPeer(peer) { if (peer.remotePublicKey.equals(publicKey)) { clearTimeout(timeoutId) diff --git a/src/sync/core-sync-state.js b/src/sync/core-sync-state.js index ff9517418..0b8caea25 100644 --- a/src/sync/core-sync-state.js +++ b/src/sync/core-sync-state.js @@ -2,6 +2,8 @@ import { keyToId } from '../utils.js' import RemoteBitfield, { BITS_PER_PAGE, } from '../core-manager/remote-bitfield.js' +/** @typedef {import('../types.js').HypercoreRemoteBitfield} HypercoreRemoteBitfield */ +/** @typedef {import('../types.js').HypercorePeer} HypercorePeer */ /** * @typedef {RemoteBitfield} Bitfield @@ -192,7 +194,7 @@ export class CoreSyncState { * emit state updates whenever the peer remote bitfield changes * * (defined as class field to bind to `this`) - * @param {any} peer + * @param {HypercorePeer} peer */ #onPeerAdd = (peer) => { const peerId = keyToId(peer.remotePublicKey) @@ -217,11 +219,11 @@ export class CoreSyncState { // a result of these two internal calls. const originalOnBitfield = peer.onbitfield const originalOnRange = peer.onrange - peer.onbitfield = (/** @type {any[]} */ ...args) => { + peer.onbitfield = (...args) => { originalOnBitfield.apply(peer, args) this.#update() } - peer.onrange = (/** @type {any[]} */ ...args) => { + peer.onrange = (...args) => { originalOnRange.apply(peer, args) this.#update() } @@ -231,7 +233,7 @@ export class CoreSyncState { * Handle a peer being removed - keeps it in state, but sets state.connected = false * * (defined as class field to bind to `this`) - * @param {any} peer + * @param {HypercorePeer} peer */ #onPeerRemove = (peer) => { const peerId = keyToId(peer.remotePublicKey) @@ -253,7 +255,7 @@ export class CoreSyncState { export class PeerState { /** @type {Bitfield} */ #preHaves = new RemoteBitfield() - /** @type {Bitfield | undefined} */ + /** @type {HypercoreRemoteBitfield | undefined} */ #haves /** @type {Bitfield} */ #wants = new RemoteBitfield() @@ -274,7 +276,7 @@ export class PeerState { return this.#preHaves.insert(start, bitfield) } /** - * @param {Bitfield} bitfield + * @param {HypercoreRemoteBitfield} bitfield */ setHavesBitfield(bitfield) { this.#haves = bitfield @@ -434,7 +436,7 @@ export function bitCount32(n) { /** * Get a 32-bit "chunk" (word) of the bitfield. * - * @param {RemoteBitfield} bitfield + * @param {Bitfield | HypercoreRemoteBitfield} bitfield * @param {number} index */ function getBitfieldWord(bitfield, index) { diff --git a/src/types.ts b/src/types.ts index 3c9953774..68764ec22 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,6 +7,7 @@ import type { } from 'type-fest' import { SUPPORTED_BLOB_VARIANTS } from './blob-store/index.js' import { MapeoCommon, MapeoDoc, MapeoValue, decode } from '@mapeo/schema' +import type BigSparseArray from 'big-sparse-array' import type Protomux from 'protomux' import type NoiseStream from '@hyperswarm/secret-stream' import { Duplex } from 'streamx' @@ -105,6 +106,30 @@ export type PublicKey = Buffer export type SecretKey = Buffer export type IdentityKeyPair = KeyPair +type HypercoreRemoteBitfieldPage = { + bitfield: Uint32Array +} + +/** + * A subset of Hypercore's `RemoteBitfield` class that we use. + */ +export type HypercoreRemoteBitfield = { + _pages: BigSparseArray + get(index: number): boolean +} + +/** + * A subset of Hypercore's `Peer` class that we use. + * TODO: Contribute these types upstream. + */ +export type HypercorePeer = { + protomux: Protomux + remotePublicKey: Buffer + remoteBitfield: HypercoreRemoteBitfield + onbitfield: (options: { start: number; bitfield: Buffer }) => void + onrange: (options: { drop: boolean; start: number; length: number }) => void +} + export { NoiseStream } type ProtocolStream = Omit & { userData: Protomux