mirror of
https://github.com/fluencelabs/js-libp2p-interfaces
synced 2025-07-07 10:51:54 +00:00
Compare commits
9 Commits
fix/topolo
...
fix/types-
Author | SHA1 | Date | |
---|---|---|---|
46c98e9cf6 | |||
7fd26cf6b9 | |||
b7f10727d6 | |||
3143efd7c1 | |||
f2d6a76dcf | |||
7ccaf27e24 | |||
4e25c6e51c | |||
cba63941b0 | |||
c1cb68e043 |
@ -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 <alan.shaw@protocol.ai>",
|
||||
|
51
src/connection/connection.d.ts
vendored
51
src/connection/connection.d.ts
vendored
@ -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<void>;
|
||||
_closing: any;
|
||||
get [connectionSymbol](): boolean;
|
||||
}
|
||||
import multiaddr = require("multiaddr");
|
||||
import PeerId = require("peer-id");
|
||||
declare const connectionSymbol: unique symbol;
|
||||
|
@ -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
|
||||
|
6
src/connection/status.d.ts
vendored
6
src/connection/status.d.ts
vendored
@ -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';
|
||||
|
@ -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')
|
||||
}
|
||||
|
18
src/pubsub/errors.d.ts
vendored
18
src/pubsub/errors.d.ts
vendored
@ -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;
|
||||
}
|
||||
|
116
src/pubsub/index.d.ts
vendored
116
src/pubsub/index.d.ts
vendored
@ -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>|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<string>}
|
||||
@ -91,35 +65,38 @@ declare class PubsubBaseProtocol {
|
||||
* Topic validators are functions with the following input:
|
||||
* @type {Map<string, validator>}
|
||||
*/
|
||||
topicValidators: Map<string, validator>;
|
||||
topicValidators: Map<string, (arg0: string, arg1: InMessage) => Promise<void>>;
|
||||
_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<void>;
|
||||
protected _onPeerConnected(peerId: PeerId, conn: any): Promise<void>;
|
||||
/**
|
||||
* 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<void>}
|
||||
*/
|
||||
_processMessages(idB58Str: string, stream: any, peerStreams: import("./peer-streams")): Promise<void>;
|
||||
_processMessages(idB58Str: string, stream: any, peerStreams: PeerStreams): Promise<void>;
|
||||
/**
|
||||
* 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<Message>}
|
||||
*/
|
||||
_buildMessage(message: any): Promise<any>;
|
||||
protected _buildMessage(message: any): Promise<any>;
|
||||
/**
|
||||
* Get a list of the peer-ids that are subscribed to one topic.
|
||||
* @param {string} topic
|
||||
* @returns {Array<string>}
|
||||
*/
|
||||
getSubscribers(topic: string): string[];
|
||||
getSubscribers(topic: string): Array<string>;
|
||||
/**
|
||||
* Publishes messages to all subscribed peers
|
||||
* @override
|
||||
@ -279,31 +259,49 @@ declare class PubsubBaseProtocol {
|
||||
* @override
|
||||
* @returns {Array<String>}
|
||||
*/
|
||||
getTopics(): string[];
|
||||
getTopics(): Array<string>;
|
||||
}
|
||||
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<void>;
|
||||
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";
|
||||
|
@ -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>|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<Message>}
|
||||
*/
|
||||
@ -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
|
||||
|
9
src/pubsub/message/index.d.ts
vendored
9
src/pubsub/message/index.d.ts
vendored
@ -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 };
|
||||
|
3
src/pubsub/message/sign.d.ts
vendored
3
src/pubsub/message/sign.d.ts
vendored
@ -13,7 +13,7 @@ export function messagePublicKey(message: any): Promise<any>;
|
||||
* @param {Message} message
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
export function signMessage(peerId: import("peer-id"), message: any): Promise<any>;
|
||||
export function signMessage(peerId: PeerId, message: any): Promise<any>;
|
||||
export const SignPrefix: any;
|
||||
/**
|
||||
* Verifies the signature of the given message
|
||||
@ -21,3 +21,4 @@ export const SignPrefix: any;
|
||||
* @returns {Promise<Boolean>}
|
||||
*/
|
||||
export function verifySignature(message: any): Promise<boolean>;
|
||||
import PeerId = require("peer-id");
|
||||
|
23
src/pubsub/peer-streams.d.ts
vendored
23
src/pubsub/peer-streams.d.ts
vendored
@ -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<Uint8Array>>}
|
||||
@ -106,8 +109,8 @@ declare namespace PeerStreams {
|
||||
}
|
||||
type DuplexIterableStream = {
|
||||
sink: Sink;
|
||||
source: () => AsyncIterator<Uint8Array, any, undefined>;
|
||||
source: () => AsyncIterator<Uint8Array>;
|
||||
};
|
||||
declare const AbortController: typeof import("abort-controller");
|
||||
type Sink = (source: Uint8Array) => Promise<Uint8Array>;
|
||||
import AbortController = require("abort-controller");
|
||||
type PeerId = import("peer-id");
|
||||
type Sink = (source: Uint8Array) => Promise<Uint8Array>;
|
||||
|
@ -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
|
||||
|
5
src/pubsub/signature-policy.d.ts
vendored
5
src/pubsub/signature-policy.d.ts
vendored
@ -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';
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
14
src/pubsub/utils.d.ts
vendored
14
src/pubsub/utils.d.ts
vendored
@ -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<any>, b: any[] | Set<any>): 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> | any[], b: Set<any> | any[]): boolean;
|
||||
export function ensureArray<T>(maybeArray: T | T[]): T[];
|
||||
export function normalizeInRpcMessage<T extends unknown>(message: T, peerId?: string | undefined): T & {
|
||||
from?: string | undefined;
|
||||
peerId?: string | undefined;
|
||||
};
|
||||
export function normalizeOutRpcMessage<T extends unknown>(message: T): T & {
|
||||
from?: Uint8Array | undefined;
|
||||
data?: Uint8Array | undefined;
|
||||
};
|
||||
|
@ -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)
|
||||
|
54
src/topology/index.d.ts
vendored
54
src/topology/index.d.ts
vendored
@ -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
|
||||
* Checks if the given value is a Topology instance.
|
||||
*
|
||||
* @param {any} other
|
||||
* @returns {other is Topology}
|
||||
*/
|
||||
constructor({ min, max, handlers }: {
|
||||
min: number;
|
||||
max: number;
|
||||
handlers?: {
|
||||
onConnect?: Function;
|
||||
onDisconnect?: Function;
|
||||
};
|
||||
});
|
||||
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<string>}
|
||||
*/
|
||||
peers: Set<string>;
|
||||
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;
|
||||
};
|
||||
|
@ -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
|
||||
|
86
src/topology/multicodec-topology.d.ts
vendored
86
src/topology/multicodec-topology.d.ts
vendored
@ -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<string>} 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
|
||||
* Checks if the given value is a `MulticodecTopology` instance.
|
||||
*
|
||||
* @param {any} other
|
||||
* @returns {other is MulticodecTopology}
|
||||
*/
|
||||
constructor({ min, max, multicodecs, handlers }: {
|
||||
min: number;
|
||||
max: number;
|
||||
multicodecs: string[];
|
||||
handlers: {
|
||||
onConnect: Function;
|
||||
onDisconnect: Function;
|
||||
};
|
||||
});
|
||||
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<string>} props.protocols
|
||||
*/
|
||||
_onProtocolChange({ peerId, protocols }: {
|
||||
peerId: any;
|
||||
protocols: string[];
|
||||
peerId: PeerId;
|
||||
protocols: Array<string>;
|
||||
}): 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<Multiaddr>, protocols: Array<string>}>} peerDataIterable
|
||||
* @returns {void}
|
||||
*/
|
||||
_updatePeers(peerDataIterable: {
|
||||
id: any;
|
||||
multiaddrs: any[];
|
||||
protocols: string[];
|
||||
}[]): void;
|
||||
_updatePeers(peerDataIterable: Array<{
|
||||
id: PeerId;
|
||||
multiaddrs: Array<Multiaddr>;
|
||||
protocols: Array<string>;
|
||||
}>): 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<Handlers>;
|
||||
};
|
||||
type Handlers = {
|
||||
/**
|
||||
* - protocol "onConnect" handler
|
||||
*/
|
||||
onConnect?: Function | undefined;
|
||||
/**
|
||||
* - protocol "onDisconnect" handler
|
||||
*/
|
||||
onDisconnect?: Function | undefined;
|
||||
};
|
||||
|
@ -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<string>} 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>} handlers
|
||||
* @typedef {import('.').Handlers} Handlers
|
||||
*/
|
||||
module.exports = withIs(MulticodecTopology, { className: 'MulticodecTopology', symbolName: '@libp2p/js-interfaces/topology/multicodec-topology' })
|
||||
module.exports = MulticodecTopology
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user