kubo-rpc-client-esm-cjs
Version:
A client library for the Kubo RPC API
179 lines • 8.46 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSubscribe = void 0;
const logger_1 = require("@libp2p/logger");
const configure_js_1 = require("../lib/configure.js");
const to_url_search_params_js_1 = require("../lib/to-url-search-params.js");
const http_rpc_wire_format_js_1 = require("../lib/http-rpc-wire-format.js");
const peer_id_1 = require("@libp2p/peer-id");
const log = (0, logger_1.logger)('js-kubo-rpc-client:pubsub:subscribe');
/**
* @param {import('../types').Options} options
* @param {import('./subscription-tracker').SubscriptionTracker} subsTracker
*/
const createSubscribe = (options, subsTracker) => {
return (0, configure_js_1.configure)((api) => {
/**
* @type {import('../types').PubsubAPI["subscribe"]}
*/
function subscribe(topic, handler, options = {}) {
return __awaiter(this, void 0, void 0, function* () {
options.signal = subsTracker.subscribe(topic, handler, options.signal);
/** @type {(value?: any) => void} */
let done;
/** @type {(error: Error) => void} */
let fail;
const result = new Promise((resolve, reject) => {
done = resolve;
fail = reject;
});
// In Firefox, the initial call to fetch does not resolve until some data
// is received. If this doesn't happen within 1 second assume success
const ffWorkaround = setTimeout(() => done(), 1000);
// Do this async to not block Firefox
api.post('pubsub/sub', {
signal: options.signal,
searchParams: (0, to_url_search_params_js_1.toUrlSearchParams)(Object.assign({ arg: (0, http_rpc_wire_format_js_1.textToUrlSafeRpc)(topic) }, options)),
headers: options.headers
})
.catch((err) => {
// Initial subscribe fail, ensure we clean up
subsTracker.unsubscribe(topic, handler);
fail(err);
})
.then((response) => {
clearTimeout(ffWorkaround);
if (!response) {
// if there was no response, the subscribe failed
return;
}
readMessages(response, {
onMessage: (message) => {
if (!handler) {
return;
}
if (typeof handler === 'function') {
handler(message);
return;
}
if (typeof handler.handleEvent === 'function') {
handler.handleEvent(message);
}
},
onEnd: () => subsTracker.unsubscribe(topic, handler),
onError: options.onError
});
done();
});
return result;
});
}
return subscribe;
})(options);
};
exports.createSubscribe = createSubscribe;
/**
* @param {import('../types').ExtendedResponse} response
* @param {object} options
* @param {(message: import('../types').Message) => void} options.onMessage
* @param {() => void} options.onEnd
* @param {import('../types').PubsubApiErrorHandlerFn} [options.onError]
*/
function readMessages(response, { onMessage, onEnd, onError }) {
var _a, e_1, _b, _c;
var _d, _e;
return __awaiter(this, void 0, void 0, function* () {
onError = onError || log;
try {
try {
for (var _f = true, _g = __asyncValues(response.ndjson()), _h; _h = yield _g.next(), _a = _h.done, !_a;) {
_c = _h.value;
_f = false;
try {
const msg = _c;
try {
if (!msg.from) {
// eslint-disable-next-line no-continue
continue;
}
if (msg.from != null && msg.seqno != null) {
onMessage({
type: 'signed',
from: (0, peer_id_1.peerIdFromString)(msg.from),
data: (0, http_rpc_wire_format_js_1.rpcToBytes)(msg.data),
sequenceNumber: (0, http_rpc_wire_format_js_1.rpcToBigInt)(msg.seqno),
topic: (0, http_rpc_wire_format_js_1.rpcToText)(msg.topicIDs[0]),
key: (0, http_rpc_wire_format_js_1.rpcToBytes)((_d = msg.key) !== null && _d !== void 0 ? _d : 'u'),
signature: (0, http_rpc_wire_format_js_1.rpcToBytes)((_e = msg.signature) !== null && _e !== void 0 ? _e : 'u')
});
}
else {
onMessage({
type: 'unsigned',
data: (0, http_rpc_wire_format_js_1.rpcToBytes)(msg.data),
topic: (0, http_rpc_wire_format_js_1.rpcToText)(msg.topicIDs[0])
});
}
}
catch ( /** @type {any} */err) {
err.message = `Failed to parse pubsub message: ${err.message}`;
onError(err, false, msg); // Not fatal
}
}
finally {
_f = true;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_f && !_a && (_b = _g.return)) yield _b.call(_g);
}
finally { if (e_1) throw e_1.error; }
}
}
catch ( /** @type {any} */err) {
if (!isAbortError(err)) {
onError(err, true); // Fatal
}
}
finally {
onEnd();
}
});
}
/**
* @param {Error & {type?:string}} error
* @returns {boolean}
*/
const isAbortError = error => {
switch (error.type) {
case 'aborted':
return true;
// It is `abort` in Electron instead of `aborted`
case 'abort':
return true;
default:
// FIXME: In testing with Chrome, err.type is undefined (should not be!)
// Temporarily use the name property instead.
return error.name === 'AbortError';
}
};
//# sourceMappingURL=subscribe.js.map