UNPKG

box-node-sdk

Version:

Official SDK for Box Platform APIs

178 lines 7.82 kB
"use strict"; 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EventStream = void 0; const errors_1 = require("./errors"); const utilsNode_1 = require("../internal/utilsNode"); var RealtimeServerEventValue; (function (RealtimeServerEventValue) { RealtimeServerEventValue["NEW_CHANGE"] = "new_change"; RealtimeServerEventValue["RECONNECT"] = "reconnect"; })(RealtimeServerEventValue || (RealtimeServerEventValue = {})); /** * EventStream is a readable stream that fetches events from the Box API. * It uses long polling to receive real-time updates. * This class is designed to be used with Node.js streams. * * @param {EventsManager} options.eventsManager - The EventsManager instance which provides relevant methods to fetch events. * @param {GetEventsQueryParams} options.queryParams - The query parameters to use for fetching events. * @param {GetEventsHeadersInput} options.headersInput - The headers to include in the request. */ class EventStream extends utilsNode_1.ByteStream { constructor(options) { super({ objectMode: true, }); this._longPollingRetries = 0; this._started = false; this._deduplicationFilterSize = 1000; this._dedupHash = new Map(); this._eventsManager = options.eventsManager; this._streamPosition = options.queryParams.streamPosition || 'now'; this._queryParams = options.queryParams; this._headersInput = options.headersInput; this._abortController = new AbortController(); this._dedupHash = new Map(); } _read(size) { if (this.destroyed) { return; } if (!this._started) { this._started = true; this.fetchEvents(); } } _destroy(error, callback) { var _a; (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.abort('Stream destroyed'); if (!error) { this.push(null); } callback(error); } getLongPollInfo() { return __awaiter(this, void 0, void 0, function* () { var _a, _b; if (this.destroyed) { return; } try { const info = yield this._eventsManager.getEventsWithLongPolling(undefined, (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.signal); const server = ((_b = info.entries) === null || _b === void 0 ? void 0 : _b.find((entry) => entry.type === 'realtime_server')) || undefined; if (!server) { throw new errors_1.BoxSdkError({ message: 'No realtime server found in the response.', }); } this._longPollingInfo = server; this._longPollingRetries = 0; return this.doLongPoll(); } catch (error) { if (error.name !== 'AbortError') { this.emit('error', error); return this.getLongPollInfo(); } } }); } doLongPoll() { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; if (this.destroyed) { return; } try { if (!this._longPollingInfo || this._longPollingRetries > parseInt(((_a = this._longPollingInfo) === null || _a === void 0 ? void 0 : _a.maxRetries) || '10', 10)) { return this.getLongPollInfo(); } this._longPollingRetries++; const longPollUrl = (_b = this._longPollingInfo) === null || _b === void 0 ? void 0 : _b.url; const longPollWithStreamPosition = `${longPollUrl}${longPollUrl.includes('?') ? '&' : '?'}stream_position=${this._streamPosition}`; const response = yield this._eventsManager.networkSession.networkClient.fetch({ url: longPollWithStreamPosition, method: 'GET', headers: { 'Content-Type': 'application/json', }, responseFormat: 'json', auth: this._eventsManager.auth, networkSession: this._eventsManager.networkSession, cancellationToken: (_c = this._abortController) === null || _c === void 0 ? void 0 : _c.signal, }); if (this.destroyed) { return; } if (response.data) { const message = response.data; if (message.message === RealtimeServerEventValue.NEW_CHANGE) { return this.fetchEvents(); } else if (message.message === RealtimeServerEventValue.RECONNECT) { return this.getLongPollInfo(); } return this.doLongPoll(); } } catch (error) { if (error.name !== 'AbortError') { this.emit('error', error); this.doLongPoll(); } } }); } fetchEvents() { return __awaiter(this, void 0, void 0, function* () { var _a, _b; if (this.destroyed) { return; } try { const events = yield this._eventsManager.getEvents(Object.assign(Object.assign({}, this._queryParams), { streamPosition: this._streamPosition, }), this._headersInput, (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.signal); this._streamPosition = ((_b = events.nextStreamPosition) === null || _b === void 0 ? void 0 : _b.toString()) || 'now'; if (events.entries) { for (const entry of events.entries) { if (entry.eventId) { if (this._dedupHash.has(entry.eventId)) { continue; } this._dedupHash.set(entry.eventId, true); } this.push(entry); } if (this._dedupHash.size >= this._deduplicationFilterSize) { for (const [key] of this._dedupHash) { if (!events.entries.some((entry) => entry.eventId === key)) { this._dedupHash.delete(key); } } } } return this.doLongPoll(); } catch (error) { if (error.name !== 'AbortError') { this.emit('error', error); this.fetchEvents(); } } }); } } exports.EventStream = EventStream; //# sourceMappingURL=eventStream.js.map