@nexica/nestjs-trpc
Version:
NestJS TRPC Bridge
215 lines • 9.45 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 __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