From 00b902d26ac0a763055562f9ff463117cbfc3810 Mon Sep 17 00:00:00 2001 From: Evan Hahn Date: Tue, 10 Sep 2024 19:16:23 +0000 Subject: [PATCH] chore: use separate helper file for NoiseSecretStreams This change should have no impact on functionality. This change creates `src/lib/noise-secret-stream-helpers.js`. It moves `openedNoiseSecretStream()` and two types in there. It also tweaks the types for `OpenedNoiseStream` and `DestroyedNoiseStream`. I think this is a useful change on its own but may also make an upcoming change easier. --- src/discovery/local-discovery.js | 2 +- src/lib/noise-secret-stream-helpers.js | 37 ++++++++++++++++++++++++++ src/local-peers.js | 7 ++--- src/mapeo-manager.js | 3 ++- src/sync/peer-sync-controller.js | 3 ++- src/sync/sync-api.js | 3 ++- src/utils.js | 22 --------------- tests/discovery/local-discovery.js | 2 +- 8 files changed, 49 insertions(+), 30 deletions(-) create mode 100644 src/lib/noise-secret-stream-helpers.js diff --git a/src/discovery/local-discovery.js b/src/discovery/local-discovery.js index fc181a139..24635bb86 100644 --- a/src/discovery/local-discovery.js +++ b/src/discovery/local-discovery.js @@ -9,7 +9,7 @@ import StartStopStateMachine from 'start-stop-state-machine' import pTimeout from 'p-timeout' import { keyToPublicId } from '@mapeo/crypto' import { Logger } from '../logger.js' -/** @import { OpenedNoiseStream } from '../utils.js' */ +/** @import { OpenedNoiseStream } from '../lib/noise-secret-stream-helpers.js' */ /** @typedef {{ publicKey: Buffer, secretKey: Buffer }} Keypair */ /** @typedef {OpenedNoiseStream} OpenedNetNoiseStream */ diff --git a/src/lib/noise-secret-stream-helpers.js b/src/lib/noise-secret-stream-helpers.js new file mode 100644 index 000000000..7c50c65ea --- /dev/null +++ b/src/lib/noise-secret-stream-helpers.js @@ -0,0 +1,37 @@ +/** @import { Duplex as NodeDuplex } from 'node:stream' */ +/** @import { Duplex as StreamxDuplex } from 'streamx' */ +/** @import NoiseSecretStream from '@hyperswarm/secret-stream' */ + +/** + * @internal + * @typedef {NodeDuplex | StreamxDuplex} RawStream + */ + +/** + * @template {RawStream} [T=RawStream] + * @typedef {NoiseSecretStream & { destroyed: true }} DestroyedNoiseStream + */ + +/** + * @template {RawStream} [T=RawStream] + * @typedef {NoiseSecretStream & { + * publicKey: Buffer, + * remotePublicKey: Buffer, + * handshake: Buffer, + * destroyed: false + * }} OpenedNoiseStream + */ + +/** + * Utility to await a NoiseSecretStream to open, that returns a stream with the + * correct types for publicKey and remotePublicKey (which can be null before + * stream is opened) + * + * @template {RawStream} T + * @param {NoiseSecretStream} stream + * @returns {Promise | DestroyedNoiseStream>} + */ +export async function openedNoiseSecretStream(stream) { + await stream.opened + return /** @type {OpenedNoiseStream | DestroyedNoiseStream} */ (stream) +} diff --git a/src/local-peers.js b/src/local-peers.js index a780c7fba..bb9923995 100644 --- a/src/local-peers.js +++ b/src/local-peers.js @@ -13,6 +13,7 @@ import { import pDefer from 'p-defer' import { Logger } from './logger.js' import pTimeout, { TimeoutError } from 'p-timeout' +/** @import { OpenedNoiseStream } from './lib/noise-secret-stream-helpers.js' */ // Unique identifier for the mapeo rpc protocol const PROTOCOL_NAME = 'mapeo/rpc' @@ -387,7 +388,7 @@ export class LocalPeers extends TypedEmitter { } /** - * @param {Protomux} protomux + * @param {Protomux} protomux * @param {() => void} done */ #makePeer(protomux, done) { @@ -460,7 +461,7 @@ export class LocalPeers extends TypedEmitter { } /** - * @param {Protomux} protomux + * @param {Protomux} protomux */ #getPeerByProtomux(protomux) { // We could also index peers by protomux to avoid this, but that would mean @@ -511,7 +512,7 @@ export class LocalPeers extends TypedEmitter { /** * - * @param {Protomux} protomux + * @param {Protomux} protomux * @param {keyof typeof MESSAGE_TYPES} type * @param {Buffer} value */ diff --git a/src/mapeo-manager.js b/src/mapeo-manager.js index 7f53d2fa9..956dc6709 100644 --- a/src/mapeo-manager.js +++ b/src/mapeo-manager.js @@ -27,12 +27,12 @@ import { deNullify, getDeviceId, keyToId, - openedNoiseSecretStream, projectIdToNonce, projectKeyToId, projectKeyToProjectInviteId, projectKeyToPublicId, } from './utils.js' +import { openedNoiseSecretStream } from './lib/noise-secret-stream-helpers.js' import { RandomAccessFilePool } from './core-manager/random-access-file-pool.js' import BlobServerPlugin from './fastify-plugins/blobs.js' import IconServerPlugin from './fastify-plugins/icons.js' @@ -51,6 +51,7 @@ import { /** @import { ProjectSettingsValue as ProjectValue } from '@mapeo/schema' */ /** @import { SetNonNullable } from 'type-fest' */ /** @import { CoreStorage, Namespace } from './types.js' */ +/** @import { OpenedNoiseStream } from './lib/noise-secret-stream-helpers.js' */ /** @typedef {SetNonNullable} ValidatedProjectKeys */ diff --git a/src/sync/peer-sync-controller.js b/src/sync/peer-sync-controller.js index 9e3abe1c7..5f442f42f 100644 --- a/src/sync/peer-sync-controller.js +++ b/src/sync/peer-sync-controller.js @@ -7,6 +7,7 @@ import { unreplicate } from '../lib/hypercore-helpers.js' /** @import { Role } from '../roles.js' */ /** @import { SyncEnabledState } from './sync-api.js' */ /** @import { Namespace } from '../types.js' */ +/** @import { OpenedNoiseStream } from '../lib/noise-secret-stream-helpers.js' */ /** * @typedef {Role['sync'][Namespace] | 'unknown'} SyncCapability @@ -35,7 +36,7 @@ export class PeerSyncController { /** * @param {object} opts - * @param {import("protomux")} opts.protomux + * @param {import('protomux')} opts.protomux * @param {import("../core-manager/index.js").CoreManager} opts.coreManager * @param {import("./sync-state.js").SyncState} opts.syncState * @param {import('../roles.js').Roles} opts.roles diff --git a/src/sync/sync-api.js b/src/sync/sync-api.js index d7bf17880..7002bae31 100644 --- a/src/sync/sync-api.js +++ b/src/sync/sync-api.js @@ -11,6 +11,7 @@ import { ExhaustivenessError, assert, keyToId, noop } from '../utils.js' import { NO_ROLE_ID } from '../roles.js' /** @import { CoreOwnership as CoreOwnershipDoc } from '@mapeo/schema' */ /** @import { CoreOwnership } from '../core-ownership.js' */ +/** @import { OpenedNoiseStream } from '../lib/noise-secret-stream-helpers.js' */ export const kHandleDiscoveryKey = Symbol('handle discovery key') export const kSyncState = Symbol('sync state') @@ -359,7 +360,7 @@ export class SyncApi extends TypedEmitter { * will then handle validation of role records to ensure that the peer is * actually still part of the project. * - * @param {{ protomux: import('protomux') }} peer + * @param {{ protomux: import('protomux') }} peer */ #handlePeerAdd = (peer) => { const { protomux } = peer diff --git a/src/utils.js b/src/utils.js index 484c0ceb3..2a86bbf4e 100644 --- a/src/utils.js +++ b/src/utils.js @@ -3,9 +3,6 @@ import sodium from 'sodium-universal' import { keyToPublicId } from '@mapeo/crypto' import { createHash } from 'node:crypto' import stableStringify from 'json-stable-stringify' -/** @import { Duplex as NodeDuplex } from 'node:stream' */ -/** @import { Duplex as StreamxDuplex } from 'streamx' */ -/** @import NoiseStream from '@hyperswarm/secret-stream' */ const PROJECT_INVITE_ID_SALT = Buffer.from('mapeo project invite id', 'ascii') @@ -46,25 +43,6 @@ export function parseVersion(version) { } } -/** @typedef {NoiseStream & { destroyed: true }} DestroyedNoiseStream */ -/** - * @template {NodeDuplex | StreamxDuplex} [T=NodeDuplex | StreamxDuplex] - * @typedef {NoiseStream & { publicKey: Buffer, remotePublicKey: Buffer, handshake: Buffer }} OpenedNoiseStream - */ - -/** - * Utility to await a NoiseSecretStream to open, that returns a stream with the - * correct types for publicKey and remotePublicKey (which can be null before - * stream is opened) - * - * @param {NoiseStream} stream - * @returns {Promise} - */ -export async function openedNoiseSecretStream(stream) { - await stream.opened - return /** @type {OpenedNoiseStream | DestroyedNoiseStream} */ (stream) -} - export class ExhaustivenessError extends Error { /** @param {never} value */ constructor(value) { diff --git a/tests/discovery/local-discovery.js b/tests/discovery/local-discovery.js index 10bdf47f4..6c15c9d67 100644 --- a/tests/discovery/local-discovery.js +++ b/tests/discovery/local-discovery.js @@ -12,7 +12,7 @@ import { LocalDiscovery, } from '../../src/discovery/local-discovery.js' import NoiseSecretStream from '@hyperswarm/secret-stream' -/** @import { OpenedNoiseStream } from '../../src/utils.js' */ +/** @import { OpenedNoiseStream } from '../../src/lib/noise-secret-stream-helpers.js' */ test('peer discovery - discovery and sharing of data', async (t) => { const deferred = pDefer()