ipfs-http-client
Version:
A client library for the IPFS HTTP API
81 lines • 2.39 kB
JavaScript
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
import debug from 'debug';
import { configure } from '../lib/configure.js';
import { toUrlSearchParams } from '../lib/to-url-search-params.js';
const log = debug('ipfs-http-client:pubsub:subscribe');
export const createSubscribe = (options, subsTracker) => {
return configure(api => {
async function subscribe(topic, handler, options = {}) {
options.signal = subsTracker.subscribe(topic, handler, options.signal);
let done;
let fail;
const result = new Promise((resolve, reject) => {
done = resolve;
fail = reject;
});
const ffWorkaround = setTimeout(() => done(), 1000);
api.post('pubsub/sub', {
signal: options.signal,
searchParams: toUrlSearchParams({
arg: topic,
...options
}),
headers: options.headers
}).catch(err => {
subsTracker.unsubscribe(topic, handler);
fail(err);
}).then(response => {
clearTimeout(ffWorkaround);
if (!response) {
return;
}
readMessages(response, {
onMessage: handler,
onEnd: () => subsTracker.unsubscribe(topic, handler),
onError: options.onError
});
done();
});
return result;
}
return subscribe;
})(options);
};
async function readMessages(response, {onMessage, onEnd, onError}) {
onError = onError || log;
try {
for await (const msg of response.ndjson()) {
try {
if (!msg.from) {
continue;
}
onMessage({
from: uint8ArrayToString(uint8ArrayFromString(msg.from, 'base64pad'), 'base58btc'),
data: uint8ArrayFromString(msg.data, 'base64pad'),
seqno: uint8ArrayFromString(msg.seqno, 'base64pad'),
topicIDs: msg.topicIDs
});
} catch (err) {
err.message = `Failed to parse pubsub message: ${ err.message }`;
onError(err, false, msg);
}
}
} catch (err) {
if (!isAbortError(err)) {
onError(err, true);
}
} finally {
onEnd();
}
}
const isAbortError = error => {
switch (error.type) {
case 'aborted':
return true;
case 'abort':
return true;
default:
return error.name === 'AbortError';
}
};