diff --git a/package.json b/package.json index f9678d9e8..92680d9e2 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "lint": "aegir lint", "build": "aegir build", "pregenerate:types": "rimraf './src/**/*.d.ts'", - "generate:types": "tsc", + "generate:types": "tsc --build", "test": "aegir test", "test:node": "aegir test --target node", "test:browser": "aegir test --target browser", @@ -41,7 +41,6 @@ "abortable-iterator": "^3.0.0", "chai": "^4.2.0", "chai-checkmark": "^1.0.1", - "class-is": "^1.1.0", "debug": "^4.1.1", "delay": "^4.3.0", "detect-node": "^2.0.4", @@ -70,7 +69,7 @@ "aegir": "^25.0.0", "it-handshake": "^1.0.1", "rimraf": "^3.0.2", - "typescript": "3.7.5" + "typescript": "^4.0.5" }, "contributors": [ "Alan Shaw ", diff --git a/src/connection/connection.d.ts b/src/connection/connection.d.ts index f74e29693..ff6f01473 100644 --- a/src/connection/connection.d.ts +++ b/src/connection/connection.d.ts @@ -1,10 +1,16 @@ -declare const _exports: typeof Connection; -export = _exports; +export = Connection; /** * An implementation of the js-libp2p connection. * Any libp2p transport should use an upgrader to return this connection. */ declare class Connection { + /** + * Checks if the given value is a `Connection` instance. + * + * @param {any} other + * @returns {other is Connection} + */ + static isConnection(other: any): other is Connection; /** * Creates an instance of Connection. * @param {object} properties properties of the connection. @@ -24,10 +30,10 @@ declare class Connection { * @param {string} [properties.stat.encryption] connection encryption method identifier. */ constructor({ localAddr, remoteAddr, localPeer, remotePeer, newStream, close, getStreams, stat }: { - localAddr?: import("multiaddr"); - remoteAddr?: import("multiaddr"); - localPeer: import("peer-id"); - remotePeer: import("peer-id"); + localAddr: multiaddr | undefined; + remoteAddr: multiaddr | undefined; + localPeer: PeerId; + remotePeer: PeerId; newStream: Function; close: Function; getStreams: () => any[]; @@ -37,42 +43,42 @@ declare class Connection { open: string; upgraded: string; }; - multiplexer?: string; - encryption?: string; + multiplexer: string | undefined; + encryption: string | undefined; }; }); /** * Connection identifier. */ - id: any; + id: string; /** * Observed multiaddr of the local peer */ - localAddr: import("multiaddr"); + localAddr: multiaddr | undefined; /** * Observed multiaddr of the remote peer */ - remoteAddr: import("multiaddr"); + remoteAddr: multiaddr | undefined; /** * Local peer id. */ - localPeer: import("peer-id"); + localPeer: PeerId; /** * Remote peer id. */ - remotePeer: import("peer-id"); + remotePeer: PeerId; /** * Connection metadata. */ _stat: { - status: string; + status: "open"; direction: string; timeline: { open: string; upgraded: string; }; - multiplexer?: string; - encryption?: string; + multiplexer?: string | undefined; + encryption?: string | undefined; }; /** * Reference to the new stream function of the multiplexer @@ -95,19 +101,20 @@ declare class Connection { * @type {string[]} */ tags: string[]; + get [Symbol.toStringTag](): string; /** * Get connection metadata * @this {Connection} */ get stat(): { - status: string; + status: "open"; direction: string; timeline: { open: string; upgraded: string; }; - multiplexer?: string; - encryption?: string; + multiplexer?: string | undefined; + encryption?: string | undefined; }; /** * Get all the streams of the muxer. @@ -133,7 +140,7 @@ declare class Connection { */ addStream(muxedStream: any, { protocol, metadata }: { protocol: string; - metadata: any; + metadata: object; }): void; /** * Remove stream registry after it is closed. @@ -146,4 +153,8 @@ declare class Connection { */ close(): Promise; _closing: any; + get [connectionSymbol](): boolean; } +import multiaddr = require("multiaddr"); +import PeerId = require("peer-id"); +declare const connectionSymbol: unique symbol; diff --git a/src/connection/connection.js b/src/connection/connection.js index d1ff248cd..57dd21566 100644 --- a/src/connection/connection.js +++ b/src/connection/connection.js @@ -1,11 +1,13 @@ 'use strict' +/* eslint-disable valid-jsdoc */ const PeerId = require('peer-id') const multiaddr = require('multiaddr') -const withIs = require('class-is') const errCode = require('err-code') const Status = require('./status') +const connectionSymbol = Symbol.for('@libp2p/interface-connection/connection') + function validateArgs (localAddr, localPeer, remotePeer, newStream, close, getStreams, stat) { if (localAddr && !multiaddr.isMultiaddr(localAddr)) { throw errCode(new Error('localAddr must be an instance of multiaddr'), 'ERR_INVALID_PARAMETERS') @@ -138,6 +140,24 @@ class Connection { this.tags = [] } + get [Symbol.toStringTag] () { + return 'Connection' + } + + get [connectionSymbol] () { + return true + } + + /** + * Checks if the given value is a `Connection` instance. + * + * @param {any} other + * @returns {other is Connection} + */ + static isConnection (other) { + return Boolean(other && other[connectionSymbol]) + } + /** * Get connection metadata * @this {Connection} @@ -227,8 +247,4 @@ class Connection { } } -/** - * @module - * @type {typeof Connection} - */ -module.exports = withIs(Connection, { className: 'Connection', symbolName: '@libp2p/interface-connection/connection' }) +module.exports = Connection diff --git a/src/connection/status.d.ts b/src/connection/status.d.ts index fc476fa00..cef75f273 100644 --- a/src/connection/status.d.ts +++ b/src/connection/status.d.ts @@ -1,3 +1,3 @@ -export declare const OPEN: string; -export declare const CLOSING: string; -export declare const CLOSED: string; +export const OPEN: 'open'; +export const CLOSING: 'closing'; +export const CLOSED: 'closed'; diff --git a/src/connection/status.js b/src/connection/status.js index 120dbad82..e585ba886 100644 --- a/src/connection/status.js +++ b/src/connection/status.js @@ -1,7 +1,7 @@ 'use strict' module.exports = { - OPEN: 'open', - CLOSING: 'closing', - CLOSED: 'closed' + OPEN: /** @type {'open'} */('open'), + CLOSING: /** @type {'closing'} */('closing'), + CLOSED: /** @type {'closed'} */('closed') } diff --git a/src/pubsub/errors.d.ts b/src/pubsub/errors.d.ts index 4bbf5b3b7..b5349d194 100644 --- a/src/pubsub/errors.d.ts +++ b/src/pubsub/errors.d.ts @@ -1,11 +1,11 @@ export namespace codes { - export const ERR_INVALID_SIGNATURE_POLICY: string; - export const ERR_UNHANDLED_SIGNATURE_POLICY: string; - export const ERR_MISSING_SIGNATURE: string; - export const ERR_MISSING_SEQNO: string; - export const ERR_INVALID_SIGNATURE: string; - export const ERR_UNEXPECTED_FROM: string; - export const ERR_UNEXPECTED_SIGNATURE: string; - export const ERR_UNEXPECTED_KEY: string; - export const ERR_UNEXPECTED_SEQNO: string; + const ERR_INVALID_SIGNATURE_POLICY: string; + const ERR_UNHANDLED_SIGNATURE_POLICY: string; + const ERR_MISSING_SIGNATURE: string; + const ERR_MISSING_SEQNO: string; + const ERR_INVALID_SIGNATURE: string; + const ERR_UNEXPECTED_FROM: string; + const ERR_UNEXPECTED_SIGNATURE: string; + const ERR_UNEXPECTED_KEY: string; + const ERR_UNEXPECTED_SEQNO: string; } diff --git a/src/pubsub/index.d.ts b/src/pubsub/index.d.ts index f2a8d1cb2..b2b26c816 100644 --- a/src/pubsub/index.d.ts +++ b/src/pubsub/index.d.ts @@ -1,40 +1,14 @@ export = PubsubBaseProtocol; -/** - * @typedef {Object} InMessage - * @property {string} [from] - * @property {string} receivedFrom - * @property {string[]} topicIDs - * @property {Uint8Array} [seqno] - * @property {Uint8Array} data - * @property {Uint8Array} [signature] - * @property {Uint8Array} [key] - * - * @typedef PeerId - * @type import('peer-id') - */ /** * PubsubBaseProtocol handles the peers and connections logic for pubsub routers * and specifies the API that pubsub routers should have. */ declare class PubsubBaseProtocol { /** - * @param {Object} props - * @param {String} props.debugName log namespace - * @param {Array|string} props.multicodecs protocol identificers to connect - * @param {Libp2p} props.libp2p - * @param {SignaturePolicy} [props.globalSignaturePolicy = SignaturePolicy.StrictSign] defines how signatures should be handled - * @param {boolean} [props.canRelayMessage = false] if can relay messages not subscribed - * @param {boolean} [props.emitSelf = false] if publish should emit to self, if subscribed * @abstract + * @param {Options} options */ - constructor({ debugName, multicodecs, libp2p, globalSignaturePolicy, canRelayMessage, emitSelf }: { - debugName: string; - multicodecs: string | string[]; - libp2p: any; - globalSignaturePolicy?: any; - canRelayMessage?: boolean; - emitSelf?: boolean; - }); + constructor({ debugName, multicodecs, libp2p, globalSignaturePolicy, canRelayMessage, emitSelf }: Options); log: any; /** * @type {Array} @@ -91,35 +65,38 @@ declare class PubsubBaseProtocol { * Topic validators are functions with the following input: * @type {Map} */ - topicValidators: Map; + topicValidators: Map Promise>; _registrarId: any; /** * On an inbound stream opened. - * @private + * + * @protected * @param {Object} props * @param {string} props.protocol * @param {DuplexIterableStream} props.stream * @param {Connection} props.connection connection */ - _onIncomingStream({ protocol, stream, connection }: { + protected _onIncomingStream({ protocol, stream, connection }: { protocol: string; stream: any; connection: any; }): void; /** * Registrar notifies an established connection with pubsub protocol. - * @private + * + * @protected * @param {PeerId} peerId remote peer-id * @param {Connection} conn connection to the peer */ - _onPeerConnected(peerId: import("peer-id"), conn: any): Promise; + protected _onPeerConnected(peerId: PeerId, conn: any): Promise; /** * Registrar notifies a closing connection with pubsub protocol. - * @private + * + * @protected * @param {PeerId} peerId peerId * @param {Error} err error for connection end */ - _onPeerDisconnected(peerId: import("peer-id"), err: Error): void; + protected _onPeerDisconnected(peerId: PeerId, err: Error): void; /** * Register the pubsub protocol onto the libp2p node. * @returns {void} @@ -132,19 +109,21 @@ declare class PubsubBaseProtocol { stop(): void; /** * Notifies the router that a peer has been connected - * @private + * + * @protected * @param {PeerId} peerId * @param {string} protocol * @returns {PeerStreams} */ - _addPeer(peerId: import("peer-id"), protocol: string): import("./peer-streams"); + protected _addPeer(peerId: PeerId, protocol: string): PeerStreams; /** * Notifies the router that a peer has been disconnected. - * @private + * + * @protected * @param {PeerId} peerId * @returns {PeerStreams | undefined} */ - _removePeer(peerId: import("peer-id")): import("./peer-streams"); + protected _removePeer(peerId: PeerId): PeerStreams | undefined; /** * Responsible for processing each RPC message received by other peers. * @param {string} idB58Str peer id string in base58 @@ -152,7 +131,7 @@ declare class PubsubBaseProtocol { * @param {PeerStreams} peerStreams PubSub peer * @returns {Promise} */ - _processMessages(idB58Str: string, stream: any, peerStreams: import("./peer-streams")): Promise; + _processMessages(idB58Str: string, stream: any, peerStreams: PeerStreams): Promise; /** * Handles an rpc request from a peer * @param {String} idB58Str @@ -160,7 +139,7 @@ declare class PubsubBaseProtocol { * @param {RPC} rpc * @returns {boolean} */ - _processRpc(idB58Str: string, peerStreams: import("./peer-streams"), rpc: any): boolean; + _processRpc(idB58Str: string, peerStreams: PeerStreams, rpc: any): boolean; /** * Handles a subscription change from a peer * @param {string} id @@ -232,17 +211,18 @@ declare class PubsubBaseProtocol { /** * Normalizes the message and signs it, if signing is enabled. * Should be used by the routers to create the message to send. - * @private + * + * @protected * @param {Message} message * @returns {Promise} */ - _buildMessage(message: any): Promise; + protected _buildMessage(message: any): Promise; /** * Get a list of the peer-ids that are subscribed to one topic. * @param {string} topic * @returns {Array} */ - getSubscribers(topic: string): string[]; + getSubscribers(topic: string): Array; /** * Publishes messages to all subscribed peers * @override @@ -279,31 +259,49 @@ declare class PubsubBaseProtocol { * @override * @returns {Array} */ - getTopics(): string[]; + getTopics(): Array; } declare namespace PubsubBaseProtocol { - export { message, utils, SignaturePolicy, InMessage, PeerId }; + export { message, utils, SignaturePolicy, Options, InMessage, PeerId, SignaturePolicyType }; } type PeerId = import("peer-id"); -/** - * Topic validator function - */ -type validator = (arg0: string, arg1: InMessage) => Promise; type InMessage = { - from?: string; + from?: string | undefined; receivedFrom: string; topicIDs: string[]; - seqno?: Uint8Array; + seqno?: Uint8Array | undefined; data: Uint8Array; - signature?: Uint8Array; - key?: Uint8Array; + signature?: Uint8Array | undefined; + key?: Uint8Array | undefined; +}; +import PeerStreams = require("./peer-streams"); +type Options = { + /** + * - log namespace + */ + debugName?: string | undefined; + /** + * - protocol identificers to connect + */ + multicodecs?: string | string[] | undefined; + libp2p: any; + /** + * - defines how signatures should be handled + */ + globalSignaturePolicy?: "StrictSign" | "StrictNoSign" | undefined; + /** + * - if can relay messages not subscribed + */ + canRelayMessage?: boolean | undefined; + /** + * - if publish should emit to self, if subscribed + */ + emitSelf?: boolean | undefined; }; /** * @type {typeof import('./message')} */ declare const message: typeof import('./message'); -declare const utils: typeof import("./utils"); -declare const SignaturePolicy: { - StrictSign: string; - StrictNoSign: string; -}; +import utils = require("./utils"); +import { SignaturePolicy } from "./signature-policy"; +type SignaturePolicyType = "StrictSign" | "StrictNoSign"; diff --git a/src/pubsub/index.js b/src/pubsub/index.js index 67619591a..ef99aecb1 100644 --- a/src/pubsub/index.js +++ b/src/pubsub/index.js @@ -1,4 +1,5 @@ 'use strict' +/* eslint-disable valid-jsdoc */ const debug = require('debug') const EventEmitter = require('events') @@ -21,34 +22,14 @@ const { verifySignature } = require('./message/sign') -/** - * @typedef {Object} InMessage - * @property {string} [from] - * @property {string} receivedFrom - * @property {string[]} topicIDs - * @property {Uint8Array} [seqno] - * @property {Uint8Array} data - * @property {Uint8Array} [signature] - * @property {Uint8Array} [key] - * - * @typedef PeerId - * @type import('peer-id') - */ - /** * PubsubBaseProtocol handles the peers and connections logic for pubsub routers * and specifies the API that pubsub routers should have. */ class PubsubBaseProtocol extends EventEmitter { /** - * @param {Object} props - * @param {String} props.debugName log namespace - * @param {Array|string} props.multicodecs protocol identificers to connect - * @param {Libp2p} props.libp2p - * @param {SignaturePolicy} [props.globalSignaturePolicy = SignaturePolicy.StrictSign] defines how signatures should be handled - * @param {boolean} [props.canRelayMessage = false] if can relay messages not subscribed - * @param {boolean} [props.emitSelf = false] if publish should emit to self, if subscribed * @abstract + * @param {Options} options */ constructor ({ debugName, @@ -205,7 +186,8 @@ class PubsubBaseProtocol extends EventEmitter { /** * On an inbound stream opened. - * @private + * + * @protected * @param {Object} props * @param {string} props.protocol * @param {DuplexIterableStream} props.stream @@ -222,7 +204,8 @@ class PubsubBaseProtocol extends EventEmitter { /** * Registrar notifies an established connection with pubsub protocol. - * @private + * + * @protected * @param {PeerId} peerId remote peer-id * @param {Connection} conn connection to the peer */ @@ -244,7 +227,8 @@ class PubsubBaseProtocol extends EventEmitter { /** * Registrar notifies a closing connection with pubsub protocol. - * @private + * + * @protected * @param {PeerId} peerId peerId * @param {Error} err error for connection end */ @@ -257,7 +241,8 @@ class PubsubBaseProtocol extends EventEmitter { /** * Notifies the router that a peer has been connected - * @private + * + * @protected * @param {PeerId} peerId * @param {string} protocol * @returns {PeerStreams} @@ -287,7 +272,8 @@ class PubsubBaseProtocol extends EventEmitter { /** * Notifies the router that a peer has been disconnected. - * @private + * + * @protected * @param {PeerId} peerId * @returns {PeerStreams | undefined} */ @@ -563,7 +549,8 @@ class PubsubBaseProtocol extends EventEmitter { /** * Normalizes the message and signs it, if signing is enabled. * Should be used by the routers to create the message to send. - * @private + * + * @protected * @param {Message} message * @returns {Promise} */ @@ -696,6 +683,27 @@ class PubsubBaseProtocol extends EventEmitter { } } +/** + * @typedef {Object} Options + * @property {string} [debugName] - log namespace + * @property {string[]|string} [multicodecs] - protocol identificers to connect + * @property {Libp2p} libp2p + * @property {SignaturePolicyType} [globalSignaturePolicy = SignaturePolicy.StrictSign] - defines how signatures should be handled + * @property {boolean} [canRelayMessage = false] - if can relay messages not subscribed + * @property {boolean} [emitSelf = false] - if publish should emit to self, if subscribed + * + * @typedef {Object} InMessage + * @property {string} [from] + * @property {string} receivedFrom + * @property {string[]} topicIDs + * @property {Uint8Array} [seqno] + * @property {Uint8Array} data + * @property {Uint8Array} [signature] + * @property {Uint8Array} [key] + * + * @typedef {import('peer-id')} PeerId + * @typedef {import('./signature-policy').SignaturePolicyType} SignaturePolicyType + */ module.exports = PubsubBaseProtocol module.exports.message = message module.exports.utils = utils diff --git a/src/pubsub/message/index.d.ts b/src/pubsub/message/index.d.ts index 62df1cefe..de14b7bef 100644 --- a/src/pubsub/message/index.d.ts +++ b/src/pubsub/message/index.d.ts @@ -1,5 +1,4 @@ -export var rpc: any; -export var td: any; -export var RPC: any; -export var Message: any; -export var SubOpts: any; +declare const rpcProto: any; +declare const topicDescriptorProto: any; +export const RPC: any; +export { rpcProto as rpc, topicDescriptorProto as td }; diff --git a/src/pubsub/message/sign.d.ts b/src/pubsub/message/sign.d.ts index 3e1bee201..0750e01a8 100644 --- a/src/pubsub/message/sign.d.ts +++ b/src/pubsub/message/sign.d.ts @@ -13,7 +13,7 @@ export function messagePublicKey(message: any): Promise; * @param {Message} message * @returns {Promise} */ -export function signMessage(peerId: import("peer-id"), message: any): Promise; +export function signMessage(peerId: PeerId, message: any): Promise; export const SignPrefix: any; /** * Verifies the signature of the given message @@ -21,3 +21,4 @@ export const SignPrefix: any; * @returns {Promise} */ export function verifySignature(message: any): Promise; +import PeerId = require("peer-id"); diff --git a/src/pubsub/peer-streams.d.ts b/src/pubsub/peer-streams.d.ts index 632fe2c84..21be2106f 100644 --- a/src/pubsub/peer-streams.d.ts +++ b/src/pubsub/peer-streams.d.ts @@ -21,7 +21,7 @@ declare class PeerStreams { * @param {string} properties.protocol */ constructor({ id, protocol }: { - id: import("peer-id"); + id: PeerId; protocol: string; }); /** @@ -35,22 +35,25 @@ declare class PeerStreams { protocol: string; /** * The raw outbound stream, as retrieved from conn.newStream - * @private + * + * @protected * @type {DuplexIterableStream} */ - _rawOutboundStream: DuplexIterableStream; + protected _rawOutboundStream: DuplexIterableStream; /** * The raw inbound stream, as retrieved from the callback from libp2p.handle - * @private + * + * @protected * @type {DuplexIterableStream} */ - _rawInboundStream: DuplexIterableStream; + protected _rawInboundStream: DuplexIterableStream; /** * An AbortController for controlled shutdown of the inbound stream - * @private + * + * @protected * @type {typeof AbortController} */ - _inboundAbortController: typeof AbortController; + protected _inboundAbortController: typeof AbortController; /** * Write stream -- its preferable to use the write method * @type {import('it-pushable').Pushable>} @@ -106,8 +109,8 @@ declare namespace PeerStreams { } type DuplexIterableStream = { sink: Sink; - source: () => AsyncIterator; + source: () => AsyncIterator; }; -declare const AbortController: typeof import("abort-controller"); -type Sink = (source: Uint8Array) => Promise; +import AbortController = require("abort-controller"); type PeerId = import("peer-id"); +type Sink = (source: Uint8Array) => Promise; diff --git a/src/pubsub/peer-streams.js b/src/pubsub/peer-streams.js index a41e1d882..6cb6d0456 100644 --- a/src/pubsub/peer-streams.js +++ b/src/pubsub/peer-streams.js @@ -48,19 +48,22 @@ class PeerStreams extends EventEmitter { this.protocol = protocol /** * The raw outbound stream, as retrieved from conn.newStream - * @private + * + * @protected * @type {DuplexIterableStream} */ this._rawOutboundStream = null /** * The raw inbound stream, as retrieved from the callback from libp2p.handle - * @private + * + * @protected * @type {DuplexIterableStream} */ this._rawInboundStream = null /** * An AbortController for controlled shutdown of the inbound stream - * @private + * + * @protected * @type {typeof AbortController} */ this._inboundAbortController = null diff --git a/src/pubsub/signature-policy.d.ts b/src/pubsub/signature-policy.d.ts index cf04e15a3..576c28c94 100644 --- a/src/pubsub/signature-policy.d.ts +++ b/src/pubsub/signature-policy.d.ts @@ -1,4 +1,5 @@ +export type SignaturePolicyType = "StrictSign" | "StrictNoSign"; export namespace SignaturePolicy { - export const StrictSign: string; - export const StrictNoSign: string; + const StrictSign: 'StrictSign'; + const StrictNoSign: 'StrictNoSign'; } diff --git a/src/pubsub/signature-policy.js b/src/pubsub/signature-policy.js index 0b5fa8cab..7bfb19323 100644 --- a/src/pubsub/signature-policy.js +++ b/src/pubsub/signature-policy.js @@ -4,7 +4,7 @@ * Enum for Signature Policy * Details how message signatures are produced/consumed */ -exports.SignaturePolicy = { +const SignaturePolicy = { /** * On the producing side: * * Build messages with the signature, key (from may be enough for certain inlineable public key types), from and seqno fields. @@ -13,7 +13,7 @@ exports.SignaturePolicy = { * * Enforce the fields to be present, reject otherwise. * * Propagate only if the fields are valid and signature can be verified, reject otherwise. */ - StrictSign: 'StrictSign', + StrictSign: /** @type {'StrictSign'} */ ('StrictSign'), /** * On the producing side: * * Build messages without the signature, key, from and seqno fields. @@ -24,5 +24,10 @@ exports.SignaturePolicy = { * * Propagate only if the fields are absent, reject otherwise. * * A message_id function will not be able to use the above fields, and should instead rely on the data field. A commonplace strategy is to calculate a hash. */ - StrictNoSign: 'StrictNoSign' + StrictNoSign: /** @type {'StrictNoSign'} */ ('StrictNoSign') } +exports.SignaturePolicy = SignaturePolicy + +/** + * @typedef {SignaturePolicy[keyof SignaturePolicy]} SignaturePolicyType + */ diff --git a/src/pubsub/utils.d.ts b/src/pubsub/utils.d.ts index f0ae093d9..3a95fdd7e 100644 --- a/src/pubsub/utils.d.ts +++ b/src/pubsub/utils.d.ts @@ -1,7 +1,13 @@ export function randomSeqno(): Uint8Array; export function msgId(from: string, seqno: Uint8Array): Uint8Array; export function noSignMsgId(data: Uint8Array): Uint8Array; -export function anyMatch(a: any[] | Set, b: any[] | Set): boolean; -export function ensureArray(maybeArray: any): any[]; -export function normalizeInRpcMessage(message: any, peerId: string): any; -export function normalizeOutRpcMessage(message: any): any; +export function anyMatch(a: Set | any[], b: Set | any[]): boolean; +export function ensureArray(maybeArray: T | T[]): T[]; +export function normalizeInRpcMessage(message: T, peerId?: string | undefined): T & { + from?: string | undefined; + peerId?: string | undefined; +}; +export function normalizeOutRpcMessage(message: T): T & { + from?: Uint8Array | undefined; + data?: Uint8Array | undefined; +}; diff --git a/src/pubsub/utils.js b/src/pubsub/utils.js index eab71681f..8ba743341 100644 --- a/src/pubsub/utils.js +++ b/src/pubsub/utils.js @@ -1,4 +1,5 @@ 'use strict' +/* eslint-disable valid-jsdoc */ const randomBytes = require('libp2p-crypto/src/random-bytes') const uint8ArrayToString = require('uint8arrays/to-string') @@ -71,8 +72,9 @@ exports.anyMatch = (a, b) => { /** * Make everything an array. * - * @param {any} maybeArray - * @returns {Array} + * @template T + * @param {T|T[]} maybeArray + * @returns {T[]} * @private */ exports.ensureArray = (maybeArray) => { @@ -85,9 +87,11 @@ exports.ensureArray = (maybeArray) => { /** * Ensures `message.from` is base58 encoded - * @param {object} message - * @param {String} peerId - * @return {object} + * + * @template {Object} T + * @param {T} message + * @param {string} [peerId] + * @return {T & {from?: string, peerId?: string }} */ exports.normalizeInRpcMessage = (message, peerId) => { const m = Object.assign({}, message) @@ -101,8 +105,10 @@ exports.normalizeInRpcMessage = (message, peerId) => { } /** - * @param {object} message - * @return {object} + * @template {Object} T + * + * @param {T} message + * @return {T & {from?: Uint8Array, data?: Uint8Array}} */ exports.normalizeOutRpcMessage = (message) => { const m = Object.assign({}, message) diff --git a/src/topology/index.d.ts b/src/topology/index.d.ts index d2e1141fa..21b300de7 100644 --- a/src/topology/index.d.ts +++ b/src/topology/index.d.ts @@ -1,23 +1,16 @@ -declare const _exports: Topology; -export = _exports; +export = Topology; declare class Topology { /** - * @param {Object} props - * @param {number} props.min minimum needed connections (default: 0) - * @param {number} props.max maximum needed connections (default: Infinity) - * @param {Object} [props.handlers] - * @param {function} [props.handlers.onConnect] protocol "onConnect" handler - * @param {function} [props.handlers.onDisconnect] protocol "onDisconnect" handler - * @constructor - */ - constructor({ min, max, handlers }: { - min: number; - max: number; - handlers?: { - onConnect?: Function; - onDisconnect?: Function; - }; - }); + * Checks if the given value is a Topology instance. + * + * @param {any} other + * @returns {other is Topology} + */ + static isTopology(other: any): other is Topology; + /** + * @param {Options} options + */ + constructor({ min, max, handlers }: Options); min: number; max: number; _onConnect: Function; @@ -27,6 +20,7 @@ declare class Topology { * @type {Set} */ peers: Set; + get [Symbol.toStringTag](): string; set registrar(arg: any); _registrar: any; /** @@ -39,4 +33,30 @@ declare class Topology { * @returns {void} */ disconnect(peerId: import("peer-id")): void; + get [topologySymbol](): boolean; } +declare namespace Topology { + export { Options, Handlers }; +} +declare const topologySymbol: unique symbol; +type Options = { + /** + * - minimum needed connections. + */ + min?: number | undefined; + /** + * - maximum needed connections. + */ + max?: number | undefined; + handlers?: Handlers | undefined; +}; +type Handlers = { + /** + * - protocol "onConnect" handler + */ + onConnect?: Function | undefined; + /** + * - protocol "onDisconnect" handler + */ + onDisconnect?: Function | undefined; +}; diff --git a/src/topology/index.js b/src/topology/index.js index 77af9293d..4dc651be7 100644 --- a/src/topology/index.js +++ b/src/topology/index.js @@ -1,17 +1,12 @@ 'use strict' +/* eslint-disable valid-jsdoc */ -const withIs = require('class-is') const noop = () => {} +const topologySymbol = Symbol.for('@libp2p/js-interfaces/topology') class Topology { /** - * @param {Object} props - * @param {number} props.min minimum needed connections (default: 0) - * @param {number} props.max maximum needed connections (default: Infinity) - * @param {Object} [props.handlers] - * @param {function} [props.handlers.onConnect] protocol "onConnect" handler - * @param {function} [props.handlers.onDisconnect] protocol "onDisconnect" handler - * @constructor + * @param {Options} options */ constructor ({ min = 0, @@ -32,6 +27,24 @@ class Topology { this.peers = new Set() } + get [Symbol.toStringTag] () { + return 'Topology' + } + + get [topologySymbol] () { + return true + } + + /** + * Checks if the given value is a Topology instance. + * + * @param {any} other + * @returns {other is Topology} + */ + static isTopology (other) { + return Boolean(other && other[topologySymbol]) + } + set registrar (registrar) { this._registrar = registrar } @@ -52,7 +65,14 @@ class Topology { } /** - * @module - * @type {Topology} + * @typedef {Object} Options + * @property {number} [min=0] - minimum needed connections. + * @property {number} [max=Infinity] - maximum needed connections. + * @property {Handlers} [handlers] + * + * @typedef {Object} Handlers + * @property {Function} [onConnect] - protocol "onConnect" handler + * @property {Function} [onDisconnect] - protocol "onDisconnect" handler */ -module.exports = withIs(Topology, { className: 'Topology', symbolName: '@libp2p/js-interfaces/topology' }) + +module.exports = Topology diff --git a/src/topology/multicodec-topology.d.ts b/src/topology/multicodec-topology.d.ts index 8752aff88..4a52993e1 100644 --- a/src/topology/multicodec-topology.d.ts +++ b/src/topology/multicodec-topology.d.ts @@ -1,27 +1,17 @@ -declare const _exports: MulticodecTopology; -export = _exports; -declare class MulticodecTopology { +export = MulticodecTopology; +declare class MulticodecTopology extends Topology { /** - * @param {Object} props - * @param {number} props.min minimum needed connections (default: 0) - * @param {number} props.max maximum needed connections (default: Infinity) - * @param {Array} props.multicodecs protocol multicodecs - * @param {Object} props.handlers - * @param {function} props.handlers.onConnect protocol "onConnect" handler - * @param {function} props.handlers.onDisconnect protocol "onDisconnect" handler - * @constructor - */ - constructor({ min, max, multicodecs, handlers }: { - min: number; - max: number; - multicodecs: string[]; - handlers: { - onConnect: Function; - onDisconnect: Function; - }; - }); + * Checks if the given value is a `MulticodecTopology` instance. + * + * @param {any} other + * @returns {other is MulticodecTopology} + */ + static isMulticodecTopology(other: any): other is MulticodecTopology; + /** + * @param {TopologyOptions & MulticodecOptions} props + */ + constructor({ min, max, multicodecs, handlers }: TopologyOptions & MulticodecOptions); multicodecs: string[]; - _registrar: any; /** * Check if a new peer support the multicodecs for this topology. * @param {Object} props @@ -29,24 +19,60 @@ declare class MulticodecTopology { * @param {Array} props.protocols */ _onProtocolChange({ peerId, protocols }: { - peerId: any; - protocols: string[]; + peerId: PeerId; + protocols: Array; }): void; /** * Verify if a new connected peer has a topology multicodec and call _onConnect. * @param {Connection} connection * @returns {void} */ - _onPeerConnect(connection: any): void; - set registrar(arg: any); + _onPeerConnect(connection: Connection): void; /** * Update topology. * @param {Array<{id: PeerId, multiaddrs: Array, protocols: Array}>} peerDataIterable * @returns {void} */ - _updatePeers(peerDataIterable: { - id: any; - multiaddrs: any[]; - protocols: string[]; - }[]): void; + _updatePeers(peerDataIterable: Array<{ + id: PeerId; + multiaddrs: Array; + protocols: Array; + }>): void; + get [multicodecTopologySymbol](): boolean; } +declare namespace MulticodecTopology { + export { PeerId, Multiaddr, Connection, TopologyOptions, MulticodecOptions, Handlers }; +} +import Topology = require("."); +type PeerId = import("peer-id"); +type Connection = typeof import("../connection"); +type Multiaddr = import("multiaddr"); +declare const multicodecTopologySymbol: unique symbol; +type TopologyOptions = { + /** + * - minimum needed connections. + */ + min?: number | undefined; + /** + * - maximum needed connections. + */ + max?: number | undefined; + handlers?: Topology.Handlers | undefined; +}; +type MulticodecOptions = { + /** + * - protocol multicodecs + */ + multicodecs: string[]; + handlers: Required; +}; +type Handlers = { + /** + * - protocol "onConnect" handler + */ + onConnect?: Function | undefined; + /** + * - protocol "onDisconnect" handler + */ + onDisconnect?: Function | undefined; +}; diff --git a/src/topology/multicodec-topology.js b/src/topology/multicodec-topology.js index 2cdc07696..c46d23d2d 100644 --- a/src/topology/multicodec-topology.js +++ b/src/topology/multicodec-topology.js @@ -1,19 +1,12 @@ 'use strict' - -const withIs = require('class-is') +/* eslint-disable valid-jsdoc */ const Topology = require('./index') +const multicodecTopologySymbol = Symbol.for('@libp2p/js-interfaces/topology/multicodec-topology') class MulticodecTopology extends Topology { /** - * @param {Object} props - * @param {number} props.min minimum needed connections (default: 0) - * @param {number} props.max maximum needed connections (default: Infinity) - * @param {Array} props.multicodecs protocol multicodecs - * @param {Object} props.handlers - * @param {function} props.handlers.onConnect protocol "onConnect" handler - * @param {function} props.handlers.onDisconnect protocol "onDisconnect" handler - * @constructor + * @param {TopologyOptions & MulticodecOptions} props */ constructor ({ min, @@ -46,6 +39,24 @@ class MulticodecTopology extends Topology { this._onPeerConnect = this._onPeerConnect.bind(this) } + get [Symbol.toStringTag] () { + return 'Topology' + } + + get [multicodecTopologySymbol] () { + return true + } + + /** + * Checks if the given value is a `MulticodecTopology` instance. + * + * @param {any} other + * @returns {other is MulticodecTopology} + */ + static isMulticodecTopology (other) { + return Boolean(other && other[multicodecTopologySymbol]) + } + set registrar (registrar) { this._registrar = registrar this._registrar.peerStore.on('change:protocols', this._onProtocolChange) @@ -106,6 +117,7 @@ class MulticodecTopology extends Topology { * @returns {void} */ _onPeerConnect (connection) { + // @ts-ignore - remotePeer does not existist on Connection const peerId = connection.remotePeer const protocols = this._registrar.peerStore.protoBook.get(peerId) @@ -121,7 +133,13 @@ class MulticodecTopology extends Topology { } /** - * @module - * @type {MulticodecTopology} + * @typedef {import('peer-id')} PeerId + * @typedef {import('multiaddr')} Multiaddr + * @typedef {import('../connection')} Connection + * @typedef {import('.').Options} TopologyOptions + * @typedef {Object} MulticodecOptions + * @property {string[]} multicodecs - protocol multicodecs + * @property {Required} handlers + * @typedef {import('.').Handlers} Handlers */ -module.exports = withIs(MulticodecTopology, { className: 'MulticodecTopology', symbolName: '@libp2p/js-interfaces/topology/multicodec-topology' }) +module.exports = MulticodecTopology diff --git a/tsconfig.json b/tsconfig.json index 482bfe877..9b19b9a6e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,20 @@ // Tells TypeScript to read JS files, as // normally they are ignored as source files "allowJs": true, + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": false, + "noImplicitAny": false, + "noImplicitThis": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": false, + "strictFunctionTypes": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "strictBindCallApply": true, + "strict": true, + "alwaysStrict": true, + "stripInternal": true, // Generate d.ts files "declaration": true, // This compiler run should