contexify
Version:
A TypeScript library providing a powerful dependency injection container with context-based IoC capabilities, inspired by LoopBack's Context system.
292 lines • 8.04 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
class TimeoutError extends Error {
static {
__name(this, "TimeoutError");
}
constructor(message) {
super(message);
this.name = "TimeoutError";
}
}
const normalizeEmitter = /* @__PURE__ */ __name((emitter) => {
const addListener = emitter.addEventListener || emitter.on || emitter.addListener;
const removeListener = emitter.removeEventListener || emitter.off || emitter.removeListener;
if (!addListener || !removeListener) {
throw new TypeError("Emitter is not compatible");
}
return {
addListener: addListener.bind(emitter),
removeListener: removeListener.bind(emitter)
};
}, "normalizeEmitter");
function pEventMultiple(emitter, event, options) {
let cancel;
const returnValue = new Promise((resolve, reject) => {
options = {
rejectionEvents: [
"error"
],
multiArgs: false,
resolveImmediately: false,
...options
};
if (!(options.count >= 0 && (options.count === Number.POSITIVE_INFINITY || Number.isInteger(options.count)))) {
throw new TypeError("The `count` option should be at least 0 or more");
}
options.signal?.throwIfAborted();
const events = Array.isArray(event) ? event : [
event
];
const items = [];
const { addListener, removeListener } = normalizeEmitter(emitter);
const onItem = /* @__PURE__ */ __name((...arguments_) => {
const value = options.multiArgs ? arguments_ : arguments_[0];
if (options.filter && !options.filter(value)) {
return;
}
items.push(value);
if (options.count === items.length) {
cancel();
resolve(items);
}
}, "onItem");
const rejectHandler = /* @__PURE__ */ __name((error) => {
cancel();
reject(error);
}, "rejectHandler");
cancel = /* @__PURE__ */ __name(() => {
for (const event2 of events) {
removeListener(event2, onItem);
}
for (const rejectionEvent of options.rejectionEvents || []) {
removeListener(rejectionEvent, rejectHandler);
}
}, "cancel");
for (const event2 of events) {
addListener(event2, onItem);
}
for (const rejectionEvent of options.rejectionEvents || []) {
addListener(rejectionEvent, rejectHandler);
}
if (options.signal) {
options.signal.addEventListener("abort", () => {
rejectHandler(options.signal.reason);
}, {
once: true
});
}
if (options.resolveImmediately) {
resolve(items);
}
});
returnValue.cancel = cancel;
if (typeof options.timeout === "number") {
const timeoutPromise = new Promise((_, reject) => {
const timer = setTimeout(() => {
returnValue.cancel();
reject(new TimeoutError(`Promise timed out after ${options.timeout} milliseconds`));
}, options.timeout);
returnValue.then(() => clearTimeout(timer), () => clearTimeout(timer));
});
const combinedPromise = Promise.race([
returnValue,
timeoutPromise
]);
combinedPromise.cancel = cancel;
return combinedPromise;
}
return returnValue;
}
__name(pEventMultiple, "pEventMultiple");
function pEvent(emitter, event, options) {
if (typeof options === "function") {
options = {
filter: options
};
}
const multipleOptions = {
...options,
count: 1,
resolveImmediately: false
};
const arrayPromise = pEventMultiple(emitter, event, multipleOptions);
const promise = arrayPromise.then((array) => array[0]);
promise.cancel = arrayPromise.cancel;
return promise;
}
__name(pEvent, "pEvent");
function pEventIterator(emitter, event, options) {
if (typeof options === "function") {
options = {
filter: options
};
}
const events = Array.isArray(event) ? event : [
event
];
options = {
rejectionEvents: [
"error"
],
resolutionEvents: [],
limit: Number.POSITIVE_INFINITY,
multiArgs: false,
...options
};
const { limit } = options;
const isValidLimit = limit >= 0 && (limit === Number.POSITIVE_INFINITY || Number.isInteger(limit));
if (!isValidLimit) {
throw new TypeError("The `limit` option should be a non-negative integer or Infinity");
}
options.signal?.throwIfAborted();
if (limit === 0) {
return {
[Symbol.asyncIterator]() {
return this;
},
async next() {
return {
done: true,
value: void 0
};
}
};
}
const { addListener, removeListener } = normalizeEmitter(emitter);
let isDone = false;
let error;
let hasPendingError = false;
const nextQueue = [];
const valueQueue = [];
let eventCount = 0;
let isLimitReached = false;
const valueHandler = /* @__PURE__ */ __name((...arguments_) => {
eventCount++;
isLimitReached = eventCount === limit;
const value = options.multiArgs ? arguments_ : arguments_[0];
if (nextQueue.length > 0) {
const { resolve } = nextQueue.shift();
resolve({
done: false,
value
});
if (isLimitReached) {
cancel();
}
return;
}
valueQueue.push(value);
if (isLimitReached) {
cancel();
}
}, "valueHandler");
const cancel = /* @__PURE__ */ __name(() => {
isDone = true;
for (const event2 of events) {
removeListener(event2, valueHandler);
}
for (const rejectionEvent of options.rejectionEvents) {
removeListener(rejectionEvent, rejectHandler);
}
for (const resolutionEvent of options.resolutionEvents) {
removeListener(resolutionEvent, resolveHandler);
}
while (nextQueue.length > 0) {
const { resolve } = nextQueue.shift();
resolve({
done: true,
value: void 0
});
}
}, "cancel");
const rejectHandler = /* @__PURE__ */ __name((...arguments_) => {
error = options.multiArgs ? arguments_ : arguments_[0];
if (nextQueue.length > 0) {
const { reject } = nextQueue.shift();
reject(error);
} else {
hasPendingError = true;
}
cancel();
}, "rejectHandler");
const resolveHandler = /* @__PURE__ */ __name((...arguments_) => {
const value = options.multiArgs ? arguments_ : arguments_[0];
if (options.filter && !options.filter(value)) {
cancel();
return;
}
if (nextQueue.length > 0) {
const { resolve } = nextQueue.shift();
resolve({
done: true,
value
});
} else {
valueQueue.push(value);
}
cancel();
}, "resolveHandler");
for (const event2 of events) {
addListener(event2, valueHandler);
}
for (const rejectionEvent of options.rejectionEvents) {
addListener(rejectionEvent, rejectHandler);
}
for (const resolutionEvent of options.resolutionEvents) {
addListener(resolutionEvent, resolveHandler);
}
if (options.signal) {
options.signal.addEventListener("abort", () => {
rejectHandler(options.signal.reason);
}, {
once: true
});
}
return {
[Symbol.asyncIterator]() {
return this;
},
async next() {
if (valueQueue.length > 0) {
const value = valueQueue.shift();
return {
done: isDone && valueQueue.length === 0 && !isLimitReached,
value
};
}
if (hasPendingError) {
hasPendingError = false;
throw error;
}
if (isDone) {
return {
done: true,
value: void 0
};
}
return new Promise((resolve, reject) => {
nextQueue.push({
resolve,
reject
});
});
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async return(value) {
cancel();
return {
done: isDone,
value
};
}
};
}
__name(pEventIterator, "pEventIterator");
export {
TimeoutError,
pEvent,
pEventIterator,
pEventMultiple
};
//# sourceMappingURL=p-event.js.map