UNPKG

@nexica/nestjs-trpc

Version:
215 lines 9.45 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()); }); }; var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createSubscriptionTester = exports.createMockEventEmitter = void 0; exports.createEventSubscription = createEventSubscription; const events_1 = require("events"); const error_handler_1 = require("../utils/error-handler"); function createEventSubscription(options) { const { eventEmitter, eventName, errorEventName = `${eventName}Error`, maxQueueSize = 1000, dropNewOnFull = false, timeout, throwOnTimeout = false, resilientMode = false, filter, transform, typeGuard, signal, onError, } = options; const eventQueue = []; let waitingResolver = null; let hasError = false; let currentError = null; let isClosed = false; const stats = { eventsProcessed: 0, errorsEncountered: 0, currentQueueSize: 0, startTime: Date.now(), lastEventTime: null, }; const processEvent = (rawEvent) => { try { if (filter && !filter(rawEvent)) { return null; } if (typeGuard && !typeGuard(rawEvent)) { error_handler_1.ErrorHandler.logError('SubscriptionHelper', `Type guard failed for event on '${eventName}'`, new Error('Type validation failed')); return null; } const processedEvent = transform ? transform(rawEvent) : rawEvent; stats.eventsProcessed++; stats.lastEventTime = Date.now(); return processedEvent; } catch (error) { error_handler_1.ErrorHandler.logError('SubscriptionHelper', `Error processing event on '${eventName}':`, error instanceof Error ? error : new Error(String(error))); return null; } }; const handler = (rawEvent) => { if (isClosed) return; const event = processEvent(rawEvent); if (event === null) return; if (waitingResolver) { waitingResolver({ event }); waitingResolver = null; } else { if (eventQueue.length >= maxQueueSize) { if (dropNewOnFull) { return; } else { eventQueue.shift(); } } eventQueue.push(event); stats.currentQueueSize = eventQueue.length; } }; const errorHandler = (error) => { stats.errorsEncountered++; if (onError) { try { onError(error, { eventName, stats: Object.assign({}, stats) }); } catch (callbackError) { error_handler_1.ErrorHandler.logError('SubscriptionHelper', `Error in custom error handler for '${eventName}':`, callbackError instanceof Error ? callbackError : new Error(String(callbackError))); } } error_handler_1.ErrorHandler.logError('SubscriptionHelper', `EventEmitter error on '${eventName}':`, error); if (resilientMode) { return; } hasError = true; currentError = error; if (waitingResolver) { waitingResolver({ error }); waitingResolver = null; } }; const cleanup = () => { if (isClosed) return; isClosed = true; eventEmitter.removeListener(eventName, handler); eventEmitter.removeListener(errorEventName, errorHandler); if (waitingResolver) { waitingResolver({ error: new Error('Subscription closed') }); waitingResolver = null; } }; if (signal) { if (signal.aborted) { throw new Error('Subscription cancelled'); } signal.addEventListener('abort', cleanup); } eventEmitter.addListener(eventName, handler); eventEmitter.addListener(errorEventName, errorHandler); const controller = { close: cleanup, isClosed: () => isClosed, getStats: () => (Object.assign(Object.assign({}, stats), { currentQueueSize: eventQueue.length })), }; const subscription = { [Symbol.asyncIterator]() { return __asyncGenerator(this, arguments, function* _a() { try { while (!isClosed) { if (hasError && !resilientMode) { throw currentError; } if (resilientMode && hasError) { hasError = false; currentError = null; } if (eventQueue.length > 0) { const event = eventQueue.shift(); stats.currentQueueSize = eventQueue.length; yield yield __await(event); continue; } const promises = [ new Promise((resolve) => { waitingResolver = resolve; }), ]; if (timeout) { promises.push(new Promise((resolve) => setTimeout(() => resolve({ timeout: true }), timeout))); } const result = yield __await(Promise.race(promises)); if ('timeout' in result) { if (throwOnTimeout) { throw new Error(`Subscription timeout after ${timeout}ms`); } continue; } if (result.error && !resilientMode) { throw result.error; } if (result.event) { yield yield __await(result.event); } } } finally { cleanup(); } }); }, }; return { subscription, controller }; } const createMockEventEmitter = () => { const emitter = new events_1.EventEmitter(); return { emitter, emit: (event, data) => emitter.emit(event, data), emitError: (event, error) => emitter.emit(`${event}Error`, error), }; }; exports.createMockEventEmitter = createMockEventEmitter; const createSubscriptionTester = (subscription) => { const iterator = subscription[Symbol.asyncIterator](); return { next: () => __awaiter(void 0, void 0, void 0, function* () { const result = yield iterator.next(); if (result.done) { throw new Error('Subscription ended'); } return result.value; }), collect: (count) => __awaiter(void 0, void 0, void 0, function* () { const results = []; for (let i = 0; i < count; i++) { const result = yield iterator.next(); if (result.done) break; results.push(result.value); } return results; }), close: () => { var _a; void ((_a = iterator.return) === null || _a === void 0 ? void 0 : _a.call(iterator)); }, }; }; exports.createSubscriptionTester = createSubscriptionTester; //# sourceMappingURL=subscription.helpers.js.map