textiot
Version:
A framework for building web and native (IoT) Dapps on the IPFS network
163 lines (162 loc) • 6.74 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const api_1 = require("../core/api");
const ponyfill_1 = require("web-streams-polyfill/ponyfill");
class EventSubscription {
constructor(cancel) {
this.cancel = cancel;
}
}
/**
* Events is an API to stream updates from an ipfs pubsub
*/
class Events extends api_1.API {
constructor(opts = api_1.DEFAULT_API_OPTIONS) {
super(opts);
this.pubsubQueryResultListeners = [];
this.queryDoneListeners = [];
this.queryErrorListeners = [];
}
addPubsubQueryResultListener(listener, queryId, queryHandle) {
this.pubsubQueryResultListeners.push({
listener,
queryId
});
// For cancellation
const isEventSubscription = new EventSubscription(() => {
this.pubsubQueryResultListeners = this.pubsubQueryResultListeners.filter((item) => item.queryId !== queryId);
this.queryDoneListeners = this.queryDoneListeners.filter((item) => item.queryId !== queryId);
this.queryErrorListeners = this.queryErrorListeners.filter((item) => item.queryId !== queryId);
if (queryHandle instanceof EventSource) {
queryHandle.close();
}
});
const onPubsubQueryEvent = (queryEvent) => {
const message = queryEvent.data.value.values[0];
const messageId = queryEvent.data.id;
for (const item of this.pubsubQueryResultListeners) {
if (item.queryId === queryEvent.id) {
item.listener(queryEvent.id, message, messageId);
}
}
};
const onQueryError = (e) => {
for (const item of this.queryErrorListeners) {
if (item.queryId === queryId) {
item.listener(queryId, e.toString());
}
}
};
const onQueryDone = () => {
for (const item of this.queryDoneListeners) {
if (item.queryId === queryId) {
item.listener(queryId);
}
}
this.pubsubQueryResultListeners = this.pubsubQueryResultListeners.filter((item) => item.queryId !== queryId);
this.queryDoneListeners = this.queryDoneListeners.filter((item) => item.queryId !== queryId);
this.queryErrorListeners = this.queryErrorListeners.filter((item) => item.queryId !== queryId);
};
if (queryHandle instanceof EventSource) {
queryHandle.addEventListener('update', (e) => {
try {
const queryEvent = JSON.parse(e.data);
onPubsubQueryEvent(queryEvent);
}
catch (e) {
onQueryError(e);
}
}, false);
queryHandle.addEventListener('open', (e) => {
// Connection was opened.
}, false);
queryHandle.addEventListener('error', (e) => {
if (e.readyState === 2 /* EventSource.CLOSED */) {
onQueryDone();
}
else {
onQueryError(e);
}
}, false);
return isEventSubscription;
}
else {
// For cancellation
let isReader;
let cancellationRequest = false;
return new ponyfill_1.ReadableStream({
start(controller) {
const reader = queryHandle.getReader();
isReader = reader;
const decoder = new TextDecoder();
let dataBuffer = '';
const processResult = (result) => {
if (result.done) {
if (cancellationRequest) {
onQueryDone();
return; // Immediately exit
}
dataBuffer = dataBuffer.trim();
if (dataBuffer.length !== 0) {
try {
const queryEvent = JSON.parse(dataBuffer);
onPubsubQueryEvent(queryEvent);
}
catch (e) {
controller.error(e);
}
}
onQueryDone();
controller.close();
return;
}
const data = decoder.decode(result.value, { stream: true });
dataBuffer += data;
const lines = dataBuffer.split('\n');
for (const line of lines) {
const l = line.trim();
if (l.length > 0) {
try {
const queryEvent = JSON.parse(l);
onPubsubQueryEvent(queryEvent);
}
catch (e) {
onQueryError(e);
controller.error(e);
break;
}
}
}
dataBuffer = lines.length > 1 ? lines[lines.length - 1] : '';
reader.read().then(processResult);
};
reader.read().then(processResult);
},
cancel(reason) {
isEventSubscription.cancel();
cancellationRequest = true;
isReader.cancel(reason);
}
});
}
}
addQueryDoneListener(listener, queryId) {
this.queryDoneListeners.push({
listener,
queryId
});
// For cancellation
const isEventSubscription = new EventSubscription(() => (this.queryDoneListeners = this.queryDoneListeners.filter((item) => item.queryId !== queryId)));
return isEventSubscription;
}
addQueryErrorListener(listener, queryId) {
this.queryErrorListeners.push({
listener,
queryId
});
// For cancellation
const isEventSubscription = new EventSubscription(() => (this.queryErrorListeners = this.queryErrorListeners.filter((item) => item.queryId !== queryId)));
return isEventSubscription;
}
}
exports.default = Events;
;