oasis/src/ssb.js

156 lines
3.7 KiB
JavaScript
Raw Normal View History

2020-01-22 00:22:19 +00:00
"use strict";
2019-08-15 01:10:22 +00:00
2020-01-09 17:04:46 +00:00
// This module exports a function that connects to SSB and returns a "cooler"
// interface. This interface is poorly defined and should be replaced with
// native support for Promises in the MuxRPC module and auto-generated manifest
// files in the SSB-Client module.
2020-01-22 00:22:19 +00:00
const ssbClient = require("ssb-client");
const ssbConfig = require("ssb-config");
const flotilla = require("@fraction/flotilla");
const debug = require("debug")("oasis");
2020-01-09 16:46:39 +00:00
2020-01-22 00:22:19 +00:00
const server = flotilla(ssbConfig);
2019-08-15 01:10:22 +00:00
const log = (...args) => {
2020-01-22 00:22:19 +00:00
const isDebugEnabled = debug.enabled;
debug.enabled = true;
debug(...args);
debug.enabled = isDebugEnabled;
};
2020-01-22 00:22:19 +00:00
const rawConnect = () =>
new Promise((resolve, reject) => {
ssbClient(
{
manifest: {
about: {
socialValue: "async",
read: "source"
},
backlinks: { read: "source" },
blobs: {
get: "source",
ls: "source",
want: "async"
},
conn: {
peers: "source"
},
createUserStream: "source",
createHistoryStream: "source",
get: "sync",
messagesByType: "source",
publish: "async",
status: "async",
tangle: { branch: "async" },
query: { read: "source" },
friends: {
isFollowing: "async",
isBlocking: "async"
},
search: {
query: "source"
}
}
2019-12-07 23:22:00 +00:00
},
2020-01-22 00:22:19 +00:00
(err, api) => {
if (err) {
reject(err);
} else {
resolve(api);
}
2019-12-07 22:58:08 +00:00
}
2020-01-22 00:22:19 +00:00
);
});
2019-07-03 18:21:47 +00:00
2020-01-22 00:22:19 +00:00
let handle;
2020-01-22 00:22:19 +00:00
const createConnection = config => {
handle = new Promise(resolve => {
rawConnect()
.then(ssb => {
log("Using pre-existing Scuttlebutt server instead of starting one");
resolve(ssb);
})
.catch(() => {
log("Initial connection attempt failed");
log("Starting Scuttlebutt server");
server(config);
const connectOrRetry = () => {
rawConnect()
.then(ssb => {
log("Retrying connection to own server");
resolve(ssb);
})
.catch(e => {
log(e);
connectOrRetry();
});
};
2020-01-22 00:22:19 +00:00
connectOrRetry();
});
});
2020-01-22 00:22:19 +00:00
return handle;
};
module.exports = ({ offline }) => {
if (offline) {
2020-01-22 00:22:19 +00:00
log("Offline mode activated - not connecting to scuttlebutt peers or pubs");
log(
"WARNING: offline mode cannot control the behavior of pre-existing servers"
);
}
const config = {
conn: {
autostart: !offline
},
ws: {
http: false
}
2020-01-22 00:22:19 +00:00
};
2020-01-22 00:22:19 +00:00
createConnection(config);
2020-01-09 17:04:46 +00:00
return {
2020-01-22 00:22:19 +00:00
connect() {
2020-01-09 17:04:46 +00:00
// This has interesting behavior that may be unexpected.
//
// If `handle` is already an active [non-closed] connection, return that.
//
// If the connection is closed, we need to restart it. It's important to
// note that if we're depending on an external service (like Patchwork) and
// that app is closed, then Oasis will seamlessly start its own SSB service.
2020-01-22 00:22:19 +00:00
return new Promise(resolve => {
handle.then(ssb => {
2020-01-09 17:04:46 +00:00
if (ssb.closed) {
2020-01-22 00:22:19 +00:00
createConnection();
2020-01-09 17:04:46 +00:00
}
2020-01-22 00:22:19 +00:00
resolve(handle);
});
});
2020-01-09 17:04:46 +00:00
},
/**
* @param {function} method
*/
2020-01-22 00:22:19 +00:00
get(method, ...opts) {
2020-01-09 17:04:46 +00:00
return new Promise((resolve, reject) => {
method(...opts, (err, val) => {
if (err) {
2020-01-22 00:22:19 +00:00
reject(err);
2020-01-09 17:04:46 +00:00
} else {
2020-01-22 00:22:19 +00:00
resolve(val);
2020-01-09 17:04:46 +00:00
}
2020-01-22 00:22:19 +00:00
});
});
2020-01-09 17:04:46 +00:00
},
2020-01-22 00:22:19 +00:00
read(method, ...args) {
return new Promise(resolve => {
resolve(method(...args));
});
2020-01-09 17:04:46 +00:00
}
2020-01-22 00:22:19 +00:00
};
};