ssb-conn
Advanced tools
Comparing version 2.1.0 to 3.0.0
@@ -0,1 +1,19 @@ | ||
# 3.0.0 | ||
- Drop support for `ssb.gossip.*` APIs, except `ssb.gossip.ping` | ||
- If you want to support `pub` messages in the scheduler, you need `ssb-db@2` or higher | ||
- Remove the deprecated APIs `ssb.conn.internalConnDB()`, `ssb.conn.internalConnHub()`, `ssb.conn.internalConnStaging()` | ||
# 2.1.0 | ||
- If already connected to a peer, `connect()` on that peer now returns the `rpc` object, not `false` | ||
# 2.0.1 | ||
- Avoids global pollution of all objects with the `.z` field, something caused by the dependency `zii` in previous versions | ||
# 2.0.0 | ||
- If you want to support `pub` messages in the scheduler, this version needs ssb-db2 and drops support for ssb-db. Everything else than `pub` messages will still work if you're on ssb-db. | ||
# 1.0.0 | ||
@@ -2,0 +20,0 @@ |
@@ -377,5 +377,5 @@ "use strict"; | ||
const MAX_STAGED_PUBS = 3; | ||
const { and, type, live, toPullStream } = this.ssb.db.operators; | ||
const { where, type, live, toPullStream } = this.ssb.db.operators; | ||
this.pubDiscoveryPausable = (_a = this.pubDiscoveryPausable) !== null && _a !== void 0 ? _a : Pausable(); | ||
pull(this.ssb.db.query(and(type('pub')), live({ old: true }), toPullStream()), pull.asyncMap((x, cb) => setTimeout(() => cb(null, x), 250)), pull.filter((msg) => { var _a; return Ref.isAddress((_a = msg.value.content) === null || _a === void 0 ? void 0 : _a.address); }), this.pubDiscoveryPausable, pull.drain((msg) => { | ||
pull(this.ssb.db.query(where(type('pub')), live({ old: true }), toPullStream()), pull.filter((msg) => { var _a; return Ref.isAddress((_a = msg.value.content) === null || _a === void 0 ? void 0 : _a.address); }), pull.asyncMap((x, cb) => setTimeout(() => cb(null, x), 250)), this.pubDiscoveryPausable, pull.drain((msg) => { | ||
try { | ||
@@ -382,0 +382,0 @@ const address = Ref.toMultiServerAddress(msg.value.content.address); |
@@ -37,5 +37,2 @@ import ConnDB = require('ssb-conn-db'); | ||
query: () => ConnQuery; | ||
internalConnDB: () => ConnDB; | ||
internalConnHub: () => ConnHub; | ||
internalConnStaging: () => ConnStaging; | ||
} |
@@ -73,14 +73,2 @@ "use strict"; | ||
this.query = () => this._query; | ||
this.internalConnDB = () => { | ||
console.error('DEPRECATED conn.internalConnDB(), use conn.db() instead'); | ||
return this._db; | ||
}; | ||
this.internalConnHub = () => { | ||
console.error('DEPRECATED conn.internalConnHub(), use conn.hub() instead'); | ||
return this._hub; | ||
}; | ||
this.internalConnStaging = () => { | ||
console.error('DEPRECATED conn.internalConnStaging(), use conn.staging() instead'); | ||
return this._staging; | ||
}; | ||
this.ssb = ssb; | ||
@@ -187,11 +175,2 @@ this.config = cfg; | ||
], CONN.prototype, "query", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], CONN.prototype, "internalConnDB", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], CONN.prototype, "internalConnHub", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], CONN.prototype, "internalConnStaging", void 0); | ||
CONN = __decorate([ | ||
@@ -198,0 +177,0 @@ secret_stack_decorators_1.plugin('1.0.0') |
@@ -1,26 +0,5 @@ | ||
import { Callback, Peer } from './types'; | ||
export declare class Gossip { | ||
private readonly ssb; | ||
private readonly notify; | ||
private readonly conn; | ||
private deprecationWarned; | ||
private latestWarning; | ||
constructor(ssb: any, cfg: any); | ||
private setupConnectionListeners; | ||
private onConnectingFailed; | ||
private onConnected; | ||
private onDisconnected; | ||
private idToAddr; | ||
private deprecationWarning; | ||
peers: () => any; | ||
get: (addr: Peer | string) => any; | ||
connect: (addr: Peer | string, cb: Callback<any>) => void; | ||
disconnect: (addr: Peer | string, cb: any) => any; | ||
changes: () => any; | ||
add: (addr: Peer | string, source: Peer['source']) => any; | ||
remove: (addr: Peer | string) => void; | ||
constructor(ssb: any); | ||
ping: () => any; | ||
reconnect: () => void; | ||
enable: (type: string) => void; | ||
disable: (type: string) => void; | ||
} |
@@ -11,289 +11,11 @@ "use strict"; | ||
const secret_stack_decorators_1 = require("secret-stack-decorators"); | ||
const pull = require('pull-stream'); | ||
const Notify = require('pull-notify'); | ||
const ref = require('ssb-ref'); | ||
function isPeerObject(o) { | ||
return o && 'object' == typeof o; | ||
} | ||
function toBase64(s) { | ||
if (typeof s === 'string') | ||
return s.substring(1, s.indexOf('.')); | ||
else | ||
return s.toString('base64'); | ||
} | ||
function toAddressString(address) { | ||
var _a; | ||
if (isPeerObject(address)) { | ||
if (ref.isAddress(address.address)) | ||
return address.address; | ||
let protocol = 'net'; | ||
if ((_a = address.host) === null || _a === void 0 ? void 0 : _a.endsWith('.onion')) | ||
protocol = 'onion'; | ||
return ([protocol, address.host, address.port].join(':') + | ||
'~' + | ||
['shs', toBase64(address.key)].join(':')); | ||
} | ||
return address; | ||
} | ||
function parseAddress(address) { | ||
const legacyParsing = ref.parseAddress(address); | ||
if (legacyParsing) { | ||
return legacyParsing; | ||
} | ||
else if (ref.isAddress(address)) { | ||
return { key: ref.getKeyFromAddress(address) }; | ||
} | ||
} | ||
function validateAddr(addr) { | ||
if (!addr || (typeof addr !== 'object' && typeof addr !== 'string')) { | ||
throw new Error('address should be an object or string'); | ||
} | ||
const addressString = typeof addr === 'string' ? addr : toAddressString(addr); | ||
const parsed = typeof addr === 'object' ? addr : parseAddress(addressString); | ||
if (!parsed.key) | ||
throw new Error('address must have ed25519 key'); | ||
if (!ref.isFeed(parsed.key)) | ||
throw new Error('key must be ed25519 public id'); | ||
return [addressString, parsed]; | ||
} | ||
function inferSource(address) { | ||
return address.startsWith('net:') ? 'local' : 'manual'; | ||
} | ||
let Gossip = class Gossip { | ||
constructor(ssb, cfg) { | ||
var _a; | ||
this.peers = () => { | ||
if (this.latestWarning + 10e3 < Date.now()) { | ||
console.trace('DEPRECATED gossip.peers(), use ssb-conn instead'); | ||
this.latestWarning = Date.now(); | ||
} | ||
const peers = Array.from(this.conn.db().entries()).map(([address, data]) => { | ||
return { | ||
...data, | ||
address, | ||
state: this.conn.hub().getState(address), | ||
}; | ||
}); | ||
for (const [address, data] of this.conn.hub().entries()) { | ||
if (!this.conn.db().has(address)) { | ||
const [, parsed] = validateAddr(address); | ||
peers.push({ | ||
...data, | ||
...parsed, | ||
address, | ||
source: inferSource(address), | ||
}); | ||
} | ||
} | ||
return peers; | ||
}; | ||
this.get = (addr) => { | ||
this.deprecationWarning('get'); | ||
if (ref.isFeed(addr)) { | ||
for (let [address, data] of this.conn.db().entries()) { | ||
if (data.key === addr) { | ||
return { ...data, address }; | ||
} | ||
} | ||
return undefined; | ||
} | ||
const [addressString] = validateAddr(addr); | ||
const peer = this.conn.db().get(addressString); | ||
if (!peer) | ||
return undefined; | ||
else { | ||
return { | ||
address: addressString, | ||
state: this.conn.hub().getState(addressString), | ||
...peer, | ||
}; | ||
} | ||
}; | ||
this.connect = (addr, cb) => { | ||
var _a, _b; | ||
this.deprecationWarning('connect'); | ||
let addressString; | ||
try { | ||
const inputAddr = ref.isFeed(addr) ? this.idToAddr(addr) : addr; | ||
[addressString] = validateAddr(inputAddr); | ||
} | ||
catch (err) { | ||
return cb(err); | ||
} | ||
this.add(addressString, 'manual'); | ||
const stagedData = (_a = this.conn.staging().get(addressString)) !== null && _a !== void 0 ? _a : {}; | ||
const dbData = (_b = this.conn.db().get(addressString)) !== null && _b !== void 0 ? _b : {}; | ||
const data = { ...dbData, ...stagedData }; | ||
this.conn.connect(addressString, data, cb); | ||
}; | ||
this.disconnect = (addr, cb) => { | ||
this.deprecationWarning('disconnect'); | ||
let addressString; | ||
try { | ||
const inputAddr = ref.isFeed(addr) ? this.idToAddr(addr) : addr; | ||
[addressString] = validateAddr(inputAddr); | ||
} | ||
catch (err) { | ||
return cb(err); | ||
} | ||
this.conn.disconnect(addressString, cb); | ||
}; | ||
this.changes = () => { | ||
this.deprecationWarning('changes'); | ||
return this.notify.listen(); | ||
}; | ||
this.add = (addr, source) => { | ||
var _a; | ||
this.deprecationWarning('add'); | ||
const [addressString, parsed] = validateAddr(addr); | ||
if (parsed.key === this.ssb.id) | ||
return; | ||
if (source === 'local') { | ||
console.error('gossip.add(p, "local") from ssb-local is deprecated, ' + | ||
'this only supports ssb-lan'); | ||
return; | ||
} | ||
if (this.conn.db().has(addressString)) { | ||
return this.conn.db().get(addressString); | ||
} | ||
else { | ||
this.conn.db().set(addressString, { | ||
host: parsed.host, | ||
port: parsed.port, | ||
key: parsed.key, | ||
address: addressString, | ||
source: source, | ||
}); | ||
this.notify({ | ||
type: 'discover', | ||
peer: { | ||
...parsed, | ||
state: this.conn.hub().getState(addressString), | ||
source: source !== null && source !== void 0 ? source : 'manual', | ||
}, | ||
source: source !== null && source !== void 0 ? source : 'manual', | ||
}); | ||
return (_a = this.conn.db().get(addressString)) !== null && _a !== void 0 ? _a : parsed; | ||
} | ||
}; | ||
this.remove = (addr) => { | ||
this.deprecationWarning('remove'); | ||
const [addressString] = validateAddr(addr); | ||
this.conn.hub().disconnect(addressString); | ||
this.conn.staging().unstage(addressString); | ||
const peer = this.conn.db().get(addressString); | ||
if (!peer) | ||
return; | ||
this.conn.db().delete(addressString); | ||
this.notify({ type: 'remove', peer: peer }); | ||
}; | ||
this.ping = () => this.conn.ping(); | ||
this.reconnect = () => { | ||
this.deprecationWarning('reconnect'); | ||
this.conn.hub().reset(); | ||
}; | ||
this.enable = (type) => { | ||
console.error('UNSUPPORTED gossip.enable("' + type + '") was ignored'); | ||
}; | ||
this.disable = (type) => { | ||
console.error('UNSUPPORTED gossip.disable("' + type + '") was ignored'); | ||
}; | ||
constructor(ssb) { | ||
this.ping = () => this.ssb.conn.ping(); | ||
this.ssb = ssb; | ||
this.notify = Notify(); | ||
this.conn = this.ssb.conn; | ||
this.latestWarning = 0; | ||
this.setupConnectionListeners(); | ||
if (((_a = cfg.conn) === null || _a === void 0 ? void 0 : _a.autostart) === false) { | ||
} | ||
else { | ||
this.conn.start(); | ||
} | ||
this.deprecationWarned = {}; | ||
} | ||
setupConnectionListeners() { | ||
pull(this.conn.hub().listen(), pull.drain((ev) => { | ||
if (ev.type === 'connecting-failed') | ||
this.onConnectingFailed(ev); | ||
if (ev.type === 'connected') | ||
this.onConnected(ev); | ||
if (ev.type === 'disconnected') | ||
this.onDisconnected(ev); | ||
})); | ||
} | ||
onConnectingFailed(ev) { | ||
const peer = { | ||
state: ev.type, | ||
address: ev.address, | ||
key: ev.key, | ||
...this.conn.db().get(ev.address), | ||
}; | ||
this.notify({ type: 'connect-failure', peer }); | ||
} | ||
onConnected(ev) { | ||
const peer = { | ||
state: ev.type, | ||
address: ev.address, | ||
key: ev.key, | ||
...this.conn.db().get(ev.address), | ||
}; | ||
if (!this.conn.db().has(ev.address)) | ||
peer.source = inferSource(ev.address); | ||
this.notify({ type: 'connect', peer }); | ||
} | ||
onDisconnected(ev) { | ||
const peer = { | ||
state: ev.type, | ||
address: ev.address, | ||
key: ev.key, | ||
...this.conn.db().get(ev.address), | ||
}; | ||
this.notify({ type: 'disconnect', peer }); | ||
} | ||
idToAddr(id) { | ||
const addr = this.conn.db().getAddressForId(id); | ||
if (!addr) { | ||
throw new Error('no known address for peer:' + id); | ||
} | ||
return addr; | ||
} | ||
deprecationWarning(method) { | ||
if (this.deprecationWarned[method]) | ||
return; | ||
console.error(`DEPRECATED gossip.${method}() was called. Use ssb-conn instead`); | ||
this.deprecationWarned[method] = true; | ||
} | ||
}; | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], Gossip.prototype, "peers", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], Gossip.prototype, "get", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('async') | ||
], Gossip.prototype, "connect", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('async') | ||
], Gossip.prototype, "disconnect", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('source') | ||
], Gossip.prototype, "changes", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], Gossip.prototype, "add", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], Gossip.prototype, "remove", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('duplex', { anonymous: 'allow' }) | ||
], Gossip.prototype, "ping", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], Gossip.prototype, "reconnect", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], Gossip.prototype, "enable", void 0); | ||
__decorate([ | ||
secret_stack_decorators_1.muxrpc('sync') | ||
], Gossip.prototype, "disable", void 0); | ||
Gossip = __decorate([ | ||
@@ -300,0 +22,0 @@ secret_stack_decorators_1.plugin('1.0.0') |
{ | ||
"name": "ssb-conn", | ||
"description": "SSB plugin for establishing and managing peer connections", | ||
"version": "2.1.0", | ||
"version": "3.0.0", | ||
"homepage": "https://github.com/staltz/ssb-conn", | ||
@@ -36,3 +36,3 @@ "main": "lib/index.js", | ||
"devDependencies": { | ||
"@types/node": "^14.11.8", | ||
"@types/node": "^14.14.37", | ||
"cont": "^1.0.3", | ||
@@ -43,5 +43,5 @@ "secret-stack": "^6.3.2", | ||
"ssb-server": "~16.0.1", | ||
"ssb-db2": "~1.18.6", | ||
"ssb-db2": "~2.0.0", | ||
"tape": "^5.2.2", | ||
"typescript": "4.2.x" | ||
"typescript": "~4.2.4" | ||
}, | ||
@@ -48,0 +48,0 @@ "scripts": { |
@@ -30,3 +30,3 @@ <div style="text-align:center" align="center"> | ||
- The default scheduler in `ssb-conn@>=2.0.0` wants to use `ssb-db2@>=1.18.0` and `ssb-friends@>=4.4.4` | ||
- The default scheduler in (older) `ssb-conn@1.0.0` wants to use `ssb-db@>=19` and `ssb-friends` | ||
- The default scheduler in (older) `ssb-conn@1.0.0` wants to use `ssb-db@>=19` and `ssb-friends` | ||
@@ -139,19 +139,9 @@ ``` | ||
The following gossip plugin APIs are available once you install CONN, but **these will emit deprecation warnings and might behave slightly different than the old gossip plugin**: | ||
The following gossip plugin APIs are available once you install CONN: | ||
| API | Type | | ||
|-----|------| | ||
| **`ssb.gossip.peers()`** | `sync` | | ||
| **`ssb.gossip.get(p)`** | `sync` | | ||
| **`ssb.gossip.connect(p)`** | `async` | | ||
| **`ssb.gossip.disconnect(p)`** | `async` | | ||
| **`ssb.gossip.changes()`** | `source` | | ||
| **`ssb.gossip.add(p, source)`** | `sync` | | ||
| **`ssb.gossip.remove(p)`** | `sync` | | ||
| **`ssb.gossip.ping()`** | `duplex` | | ||
| **`ssb.gossip.reconnect()`** | `sync` | | ||
| **`ssb.gossip.enable()`** | `sync` | | ||
| **`ssb.gossip.disable()`** | `sync` | | ||
If you want to use the new CONN infrastructure but preserve the same gossip behavior as before, use [`ssb-legacy-conn`](https://github.com/staltz/ssb-legacy-conn) which tries to mirror the gossip plugin, even its log messages. | ||
If you want to use other legacy `ssb.gossip.*` APIs and preserve the same gossip behavior as before, use [`ssb-legacy-conn`](https://github.com/staltz/ssb-legacy-conn) which uses parts of CONN and tries to mirrors the old gossip plugin as closely as possible, even its log messages. | ||
@@ -158,0 +148,0 @@ ## Recipes |
57803
961
397