one-firework
Version:
A library for singal use function execution.
85 lines (83 loc) • 3.45 kB
JavaScript
// node_modules/mimic-function/index.js
var copyProperty = (to, from, property, ignoreNonConfigurable) => {
if (property === "length" || property === "prototype") {
return;
}
if (property === "arguments" || property === "caller") {
return;
}
const toDescriptor = Object.getOwnPropertyDescriptor(to, property);
const fromDescriptor = Object.getOwnPropertyDescriptor(from, property);
if (!canCopyProperty(toDescriptor, fromDescriptor) && ignoreNonConfigurable) {
return;
}
Object.defineProperty(to, property, fromDescriptor);
};
var canCopyProperty = function(toDescriptor, fromDescriptor) {
return toDescriptor === undefined || toDescriptor.configurable || toDescriptor.writable === fromDescriptor.writable && toDescriptor.enumerable === fromDescriptor.enumerable && toDescriptor.configurable === fromDescriptor.configurable && (toDescriptor.writable || toDescriptor.value === fromDescriptor.value);
};
var changePrototype = (to, from) => {
const fromPrototype = Object.getPrototypeOf(from);
if (fromPrototype === Object.getPrototypeOf(to)) {
return;
}
Object.setPrototypeOf(to, fromPrototype);
};
var wrappedToString = (withName, fromBody) => `/* Wrapped ${withName}*/
${fromBody}`;
var toStringDescriptor = Object.getOwnPropertyDescriptor(Function.prototype, "toString");
var toStringName = Object.getOwnPropertyDescriptor(Function.prototype.toString, "name");
var changeToString = (to, from, name) => {
const withName = name === "" ? "" : `with ${name.trim()}() `;
const newToString = wrappedToString.bind(null, withName, from.toString());
Object.defineProperty(newToString, "name", toStringName);
const { writable, enumerable, configurable } = toStringDescriptor;
Object.defineProperty(to, "toString", { value: newToString, writable, enumerable, configurable });
};
function mimicFunction(to, from, { ignoreNonConfigurable = false } = {}) {
const { name } = to;
for (const property of Reflect.ownKeys(from)) {
copyProperty(to, from, property, ignoreNonConfigurable);
}
changePrototype(to, from);
changeToString(to, from, name);
return to;
}
// index.ts
var calledFunction = new WeakMap;
var firework = (function_, options = {}) => {
if (typeof function_ !== "function") {
throw new TypeError(`Expected a function, but received \`${typeof function_}\`. Please pass a function.`);
}
let originalFunction = function_;
let returnValue;
let fireCount = 0;
const functionName = function_.name || "<anonymous>";
const fireworkFunction = (...args_) => {
fireCount++;
calledFunction.set(fireworkFunction, fireCount);
if (fireCount === 1) {
try {
returnValue = originalFunction.apply(null, args_);
} finally {
originalFunction = undefined;
}
} else if (options.throwOnMaxCalls === true) {
throw new Error(`Function \`${functionName}\` can only be called once! Called \`${fireCount}\` times`);
}
return returnValue;
};
mimicFunction(fireworkFunction, originalFunction);
return fireworkFunction;
};
firework.fired = (wrappedFunction) => {
if (!calledFunction.has(wrappedFunction)) {
const funcName = wrappedFunction?.name || "<anonymous function>";
throw new Error(`The function \`${funcName}\` was not created by \`firework\` or has not been called yet.`);
}
return calledFunction.get(wrappedFunction);
};
var firework_default = firework;
export {
firework_default as default
};