Replace cooler methods with SSB-Client promises

Problem: We started using `cooler.get()` and `cooler.read()` because it
was impossible to use promises with SSB-Client.

Solution: I made some downstream pull requests into the MuxRPC module
and the SSB-Client module, which means that both of them now natively
support promises. This commit removes the weird convenience methods and
replaces them with the native promise support, which should hopefully
make the code easier to read and write.
This commit is contained in:
Christian Bundy 2020-02-11 12:48:50 -08:00
parent ca16413ad0
commit 1e28b29758
4 changed files with 119 additions and 111 deletions

48
package-lock.json generated
View File

@ -3162,9 +3162,9 @@
"integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw="
},
"highlight.js": {
"version": "9.18.0",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.0.tgz",
"integrity": "sha512-A97kI1KAUzKoAiEoaGcf2O9YPS8nbDTCRFokaaeBhnqjQTvbAuAJrQMm21zw8s8xzaMtCQBtgbyGXLGxdxQyqQ=="
"version": "9.18.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz",
"integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg=="
},
"hoox": {
"version": "0.0.1",
@ -7023,24 +7023,48 @@
"integrity": "sha512-qe3qpvchJ+gnH8M/ge4rpL+7eRbSmsEAzNwHkDdrW06OBcziQ6/KuAdmcR6joxCbNeoAXAZF+inkefgE16okXA=="
},
"ssb-client": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/ssb-client/-/ssb-client-4.8.0.tgz",
"integrity": "sha512-5nfx08Cgl176IyK1uQrHO3SBord1rUDKUJvrz9ddgYWIL78+/puk3zs26rt3BqDTPWBtd/Txdy9OLHBYNDhK8A==",
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/ssb-client/-/ssb-client-4.9.0.tgz",
"integrity": "sha512-5wPrVA82Uk3deV2oiCZEbm1kMp9r/5xTT2VvwwMLZS3fDD9FnLOi0kjUUh3OTP+jGBK7bVHRmnvXIVy6ETnSpA==",
"requires": {
"explain-error": "^1.0.1",
"multicb": "^1.2.1",
"multiserver": "^3.1.2",
"muxrpc": "^6.4.8",
"muxrpc": "^6.5.0",
"pull-hash": "^1.0.0",
"pull-stream": "^3.6.0",
"ssb-config": "^3.2.5",
"ssb-keys": "^7.0.13"
"ssb-config": "^3.4.4",
"ssb-keys": "^7.2.1"
},
"dependencies": {
"muxrpc": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/muxrpc/-/muxrpc-6.5.0.tgz",
"integrity": "sha512-8kCo33LTYPYWAJGi2Ag2ukcluoNqJIe6Ay9QtGf7EXAUlTuMSA0HqR7jCbXt7DQPR4Alu/T3/mOguuERpDMGcw==",
"requires": {
"explain-error": "^1.0.1",
"packet-stream": "~2.0.0",
"packet-stream-codec": "^1.1.1",
"pull-goodbye": "0.0.2",
"pull-stream": "^3.6.10"
}
},
"ssb-keys": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/ssb-keys/-/ssb-keys-7.2.2.tgz",
"integrity": "sha512-FPeyYU/3LpxcagnbmVWE+Q/qzg6keqeOBPbD7sEH9UKixUASeufPKiORDgh8nVX7J9Z+0vUaHt/WG999kGjvVQ==",
"requires": {
"chloride": "^2.2.8",
"mkdirp": "~0.5.0",
"private-box": "^0.3.0"
}
}
}
},
"ssb-config": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/ssb-config/-/ssb-config-3.4.3.tgz",
"integrity": "sha512-qvutXHzW+KPhopVGAc8QYJ0jKorGVVYrZBbuyTGU1sCVdtXKGqOIQGJzpiwQUdLe2UM4Sc9WWWCAYTWlSSqhkA==",
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/ssb-config/-/ssb-config-3.4.4.tgz",
"integrity": "sha512-J3fsWb5nS6PqObZLW2tclEz/bkRQ5pcF9goXanYGVsoH71F6W4f5sOnck9szeubI8srNaiL9pa0kPRv/lojHiw==",
"requires": {
"deep-extend": "^0.6.0",
"ip": "^1.1.5",

View File

@ -24,7 +24,7 @@
"@fraction/base16-css": "^1.1.0",
"@fraction/flotilla": "^4.0.0",
"debug": "^4.1.1",
"highlight.js": "^9.18.0",
"highlight.js": "^9.18.1",
"hyperaxe": "^1.3.0",
"is-svg": "^4.2.1",
"koa": "^2.7.0",
@ -40,8 +40,8 @@
"pull-stream": "^3.6.12",
"require-style": "^1.1.0",
"sharp": "^0.23.0",
"ssb-client": "^4.8.0",
"ssb-config": "^3.4.3",
"ssb-client": "^4.9.0",
"ssb-config": "^3.4.4",
"ssb-markdown": "^6.0.3",
"ssb-mentions": "^0.5.0",
"ssb-msgs": "^5.2.0",

View File

@ -41,9 +41,9 @@ module.exports = ({ cooler, isPublic }) => {
* above problems. Maybe this should be moved somewhere else in the future?
*/
const getAbout = async ({ key, feedId }) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const source = await cooler.read(ssb.backlinks.read, {
const source = await ssb.backlinks.read({
reverse: true,
query: [
{
@ -128,31 +128,31 @@ module.exports = ({ cooler, isPublic }) => {
models.blob = {
get: async ({ blobId }) => {
debug("get blob: %s", blobId);
const ssb = await cooler.connect();
return cooler.read(ssb.blobs.get, blobId);
const ssb = await cooler.open();
return ssb.blobs.get(blobId);
},
want: async ({ blobId }) => {
debug("want blob: %s", blobId);
const ssb = await cooler.connect();
const ssb = await cooler.open();
// This does not wait for the blob.
cooler.get(ssb.blobs.want, blobId);
ssb.blobs.want(blobId);
}
};
models.friend = {
isFollowing: async feedId => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const { id } = ssb;
const isFollowing = await cooler.get(ssb.friends.isFollowing, {
const isFollowing = await ssb.friends.isFollowing({
source: id,
dest: feedId
});
return isFollowing;
},
setFollowing: async ({ feedId, following }) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const content = {
type: "contact",
@ -160,7 +160,7 @@ module.exports = ({ cooler, isPublic }) => {
following
};
return cooler.get(ssb.publish, content);
return ssb.publish(content);
},
follow: async feedId => {
const isFollowing = await models.friend.isFollowing(feedId);
@ -175,19 +175,19 @@ module.exports = ({ cooler, isPublic }) => {
}
},
getRelationship: async feedId => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const { id } = ssb;
if (feedId === id) {
return null;
}
const isFollowing = await cooler.get(ssb.friends.isFollowing, {
const isFollowing = await ssb.friends.isFollowing({
source: id,
dest: feedId
});
const isBlocking = await cooler.get(ssb.friends.isBlocking, {
const isBlocking = await ssb.friends.isBlocking({
source: id,
dest: feedId
});
@ -201,25 +201,25 @@ module.exports = ({ cooler, isPublic }) => {
models.meta = {
myFeedId: async () => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const { id } = ssb;
return id;
},
get: async msgId => {
const ssb = await cooler.connect();
return cooler.get(ssb.get, {
const ssb = await cooler.open();
return ssb.get({
id: msgId,
meta: true,
private: true
});
},
status: async () => {
const ssb = await cooler.connect();
return cooler.get(ssb.status);
const ssb = await cooler.open();
return ssb.status();
},
peers: async () => {
const ssb = await cooler.connect();
const peersSource = await cooler.read(ssb.conn.peers);
const ssb = await cooler.open();
const peersSource = await ssb.conn.peers();
return new Promise((resolve, reject) => {
pull(
@ -234,10 +234,10 @@ module.exports = ({ cooler, isPublic }) => {
});
},
connStop: async () => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
try {
const result = await cooler.get(ssb.conn.stop);
const result = await ssb.conn.stop();
return result;
} catch (e) {
const expectedName = "TypeError";
@ -251,8 +251,8 @@ module.exports = ({ cooler, isPublic }) => {
}
},
connStart: async () => {
const ssb = await cooler.connect();
const result = await cooler.get(ssb.conn.start);
const ssb = await cooler.open();
const result = await ssb.conn.start();
return result;
},
@ -261,8 +261,8 @@ module.exports = ({ cooler, isPublic }) => {
await models.meta.connStart();
},
acceptInvite: async invite => {
const ssb = await cooler.connect();
return await cooler.get(ssb.invite.accept, invite);
const ssb = await cooler.open();
return await ssb.invite.accept(invite);
}
};
@ -311,7 +311,7 @@ module.exports = ({ cooler, isPublic }) => {
}) => {
const options = configure({ query, index: "DTA" }, customOptions);
const source = await cooler.read(ssb.backlinks.read, options);
const source = await ssb.backlinks.read(options);
const basicSocialFilter = await socialFilter();
return new Promise((resolve, reject) => {
@ -349,9 +349,9 @@ module.exports = ({ cooler, isPublic }) => {
blocking = false,
me = null
} = {}) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const { id } = ssb;
const relationshipObject = await cooler.get(ssb.friends.get, {
const relationshipObject = await ssb.friends.get({
source: id
});
@ -391,7 +391,7 @@ module.exports = ({ cooler, isPublic }) => {
}
};
const referenceStream = await cooler.read(ssb.backlinks.read, {
const referenceStream = await ssb.backlinks.read({
query: [filterQuery],
index: "DTA", // use asserted timestamps
private: true,
@ -512,12 +512,12 @@ module.exports = ({ cooler, isPublic }) => {
const post = {
fromPublicFeed: async (feedId, customOptions = {}) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
const options = configure({ id: feedId }, customOptions);
const source = await cooler.read(ssb.createUserStream, options);
const source = await ssb.createUserStream(options);
const messages = await new Promise((resolve, reject) => {
pull(
@ -541,7 +541,7 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
mentionsMe: async (customOptions = {}) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
@ -564,7 +564,7 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
fromHashtag: async (hashtag, customOptions = {}) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
@ -586,7 +586,7 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
threadReplies: async (rootId, customOptions = {}) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
@ -610,7 +610,7 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
likes: async ({ feed }, customOptions = {}) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const query = [
{
@ -634,7 +634,7 @@ module.exports = ({ cooler, isPublic }) => {
customOptions
);
const source = await cooler.read(ssb.query.read, options);
const source = await ssb.query.read(options);
const messages = await new Promise((resolve, reject) => {
pull(
@ -665,7 +665,7 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
search: async ({ query }) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
@ -673,7 +673,7 @@ module.exports = ({ cooler, isPublic }) => {
query
});
const source = await cooler.read(ssb.search.query, options);
const source = await ssb.search.query(options);
const messages = await new Promise((resolve, reject) => {
pull(
@ -697,7 +697,7 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
latest: async () => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
@ -706,7 +706,7 @@ module.exports = ({ cooler, isPublic }) => {
private: false
});
const source = await cooler.read(ssb.messagesByType, options);
const source = await ssb.messagesByType(options);
const followingFilter = await socialFilter({ following: true });
const messages = await new Promise((resolve, reject) => {
@ -732,7 +732,7 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
latestExtended: async () => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
@ -741,7 +741,7 @@ module.exports = ({ cooler, isPublic }) => {
private: false
});
const source = await cooler.read(ssb.messagesByType, options);
const source = await ssb.messagesByType(options);
const extendedFilter = await socialFilter({
following: false
@ -766,7 +766,7 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
latestTopics: async () => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
@ -775,7 +775,7 @@ module.exports = ({ cooler, isPublic }) => {
private: false
});
const source = await cooler.read(ssb.messagesByType, options);
const source = await ssb.messagesByType(options);
const extendedFilter = await socialFilter({
following: true
@ -804,7 +804,7 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
popular: async ({ period }) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const periodDict = {
day: 1,
@ -828,7 +828,7 @@ module.exports = ({ cooler, isPublic }) => {
private: false
});
const source = await cooler.read(ssb.messagesByType, options);
const source = await ssb.messagesByType(options);
const followingFilter = await socialFilter({ following: true });
const messages = await new Promise((resolve, reject) => {
@ -927,13 +927,13 @@ module.exports = ({ cooler, isPublic }) => {
},
fromThread: async (msgId, customOptions) => {
debug("thread: %s", msgId);
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
const options = configure({ id: msgId }, customOptions);
return cooler
.get(ssb.get, options)
return ssb
.get(options)
.then(async rawMsg => {
debug("got raw message");
@ -962,8 +962,8 @@ module.exports = ({ cooler, isPublic }) => {
debug("reply, get the parent");
try {
// It's a message reply, get the parent!
cooler
.get(ssb.get, {
ssb
.get({
id: msg.value.content.fork,
meta: true,
private: true
@ -980,8 +980,8 @@ module.exports = ({ cooler, isPublic }) => {
debug("comment: %s", msg.value.content.root);
try {
// It's a thread reply, get the parent!
cooler
.get(ssb.get, {
ssb
.get({
id: msg.value.content.root,
meta: true,
private: true
@ -1017,8 +1017,8 @@ module.exports = ({ cooler, isPublic }) => {
}
};
cooler
.read(ssb.backlinks.read, {
ssb.backlinks
.read({
query: [filterQuery],
index: "DTA" // use asserted timestamps
})
@ -1124,12 +1124,12 @@ module.exports = ({ cooler, isPublic }) => {
},
get: async (msgId, customOptions) => {
debug("get: %s", msgId);
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
const options = configure({ id: msgId }, customOptions);
const rawMsg = await cooler.get(ssb.get, options);
const rawMsg = await ssb.get(options);
debug("got raw message");
const transformed = await transform(ssb, [rawMsg], myFeedId);
@ -1137,11 +1137,11 @@ module.exports = ({ cooler, isPublic }) => {
return transformed[0];
},
publish: async options => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const body = { type: "post", ...options };
debug("Published: %O", body);
return cooler.get(ssb.publish, body);
return ssb.publish(body);
},
reply: async ({ parent, message }) => {
message.root = parent.key;
@ -1213,13 +1213,13 @@ module.exports = ({ cooler, isPublic }) => {
return post.publish(message);
},
branch: async ({ root }) => {
const ssb = await cooler.connect();
const keys = await cooler.get(ssb.tangle.branch, root);
const ssb = await cooler.open();
const keys = await ssb.tangle.branch(root);
return keys;
},
inbox: async (customOptions = {}) => {
const ssb = await cooler.connect();
const ssb = await cooler.open();
const myFeedId = ssb.id;
@ -1230,7 +1230,7 @@ module.exports = ({ cooler, isPublic }) => {
customOptions
);
const source = await cooler.read(ssb.backlinks.read, options);
const source = await ssb.backlinks.read(options);
const messages = await new Promise((resolve, reject) => {
pull(
@ -1269,10 +1269,10 @@ module.exports = ({ cooler, isPublic }) => {
models.vote = {
/** @param {{messageKey: string, value: {}, recps: []}} input */
publish: async ({ messageKey, value, recps }) => {
const ssb = await cooler.connect();
const branch = await cooler.get(ssb.tangle.branch, messageKey);
const ssb = await cooler.open();
const branch = await ssb.tangle.branch(messageKey);
await cooler.get(ssb.publish, {
await ssb.publish({
type: "vote",
vote: {
link: messageKey,

View File

@ -1,8 +1,8 @@
"use strict";
// 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.
// This module exports a function that connects to SSB and returns an interface
// to call methods over MuxRPC. It's a thin wrapper around SSB-Client, which is
// a thin wrapper around the MuxRPC module.
const ssbClient = require("ssb-client");
const ssbConfig = require("ssb-config");
@ -21,10 +21,8 @@ const log = (...args) => {
const rawConnect = () =>
new Promise((resolve, reject) => {
ssbClient((err, api) => {
if (err) {
reject(err);
} else {
ssbClient()
.then(api => {
if (api.tangle === undefined) {
// HACK: SSB-Tangle isn't available in Patchwork, but we want that
// compatibility. This code automatically injects SSB-Tangle into our
@ -35,8 +33,8 @@ const rawConnect = () =>
}
resolve(api);
}
});
})
.catch(reject);
});
let handle;
@ -89,8 +87,13 @@ module.exports = ({ offline }) => {
};
createConnection(config);
/**
* This is "cooler", a tiny interface for opening or reusing an instance of
* SSB-Client.
*/
return {
connect() {
open() {
// This has interesting behavior that may be unexpected.
//
// If `handle` is already an active [non-closed] connection, return that.
@ -106,25 +109,6 @@ module.exports = ({ offline }) => {
resolve(handle);
});
});
},
/**
* @param {function} method
*/
get(method, ...opts) {
return new Promise((resolve, reject) => {
method(...opts, (err, val) => {
if (err) {
reject(err);
} else {
resolve(val);
}
});
});
},
read(method, ...args) {
return new Promise(resolve => {
resolve(method(...args));
});
}
};
};