UNPKG

textiot

Version:

A framework for building web and native (IoT) Dapps on the IPFS network

163 lines (162 loc) 6.74 kB
"use strict"; 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;