var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/futurify-class.ts var futurify_class_exports = {}; __export(futurify_class_exports, { futurifyClass: () => futurifyClass }); module.exports = __toCommonJS(futurify_class_exports); // src/index.ts var CACHE_NOT_SET = Symbol("CACHE_NOT_SET"); var Future = class _Future { operation; dependencies; optionNoCache; value; resolving = false; resolvePromise; clear = false; constructor(operation, dependencies, optionNoCache = false) { this.operation = operation; this.dependencies = Object.freeze(dependencies || []); this.optionNoCache = optionNoCache; this.value = CACHE_NOT_SET; } static resolve(value) { return value instanceof _Future ? value : new _Future(() => value); } static async resolveOperation(operation, dependencies) { const resolvedDependencies = await Promise.all(dependencies); return operation(...resolvedDependencies); } async cachedResolveOperation(operation, dependencies) { const resolver = async () => { if (this.resolving) { return this.resolvePromise; } this.resolving = true; try { if (this.optionNoCache) { return _Future.resolveOperation(operation, dependencies); } this.value = await _Future.resolveOperation(operation, dependencies); return this.value; } finally { this.resolving = false; } }; if (this.value !== CACHE_NOT_SET && !this.clear) { return this.value; } if (this.clear) this.clear = false; this.resolvePromise = resolver(); return this.resolvePromise; } resolve({ /** clears the cache */ clear = false } = {}) { if (clear) this.clear = true; return this.cachedResolveOperation(this.operation, this.dependencies); } then(onfulfilled, onrejected) { return this.resolve().then(onfulfilled, onrejected); } catch(onrejected) { return this.resolve().catch(onrejected); } finally(onfinally) { return this.resolve().finally(onfinally); } /** clones Future and deps with noCache, depth 0 is current Future */ noCache(depth = 0) { const shouldNoCache = depth >= 0; const shouldNoCacheDeps = depth > 0; const clonedDependencies = shouldNoCacheDeps ? this.dependencies.map((dep) => { return dep instanceof _Future ? dep.noCache(depth - 1) : dep; }) : this.dependencies; return shouldNoCache ? new _Future(this.operation, clonedDependencies, true) : this; } /** clones Future and clears cache values, depth 0 is current Future */ clone(depth = 0) { const shouldClone = depth >= 0; const shouldCloneDeps = depth > 0; const clonedDependencies = shouldCloneDeps ? this.dependencies.map((dep) => { return dep instanceof _Future ? dep.clone(depth - 1) : dep; }) : this.dependencies; return shouldClone ? new _Future(this.operation, clonedDependencies) : this; } /** creates a new future using this future as a dependency */ use(operation, dependencies = []) { return new _Future( async (resolvedValue, ...args) => { return operation(resolvedValue, ...args); }, [this, ...dependencies] ); } /** updates future value */ update(operation, dependencies = []) { const originalOperation = this.operation; this.operation = async () => { const currentValue = this.value !== CACHE_NOT_SET ? this.value : await _Future.resolveOperation(originalOperation, this.dependencies); return _Future.resolveOperation(operation, [currentValue, ...dependencies]); }; this.clear = true; return this; } }; // src/futurify-class.ts function getTypeOf(Class, prop) { try { if (Reflect.has(Class, prop)) { return typeof Class[prop]; } if (Reflect.has(Class.prototype, prop)) { return typeof Class.prototype[prop]; } return "undefined"; } catch (error) { return `Error: ${error.message}`; } } function futurifyClass(Class) { const getInstanceProxy = (instance) => new Proxy( {}, { get(_, prop) { if (prop === "then") { return instance.then.bind(instance); } if (getTypeOf(Class, prop) === "function") { return (...args) => { const future = new Future( async (resolvedInstance) => { const rargs = await Promise.all(args); const result = await resolvedInstance[prop](...rargs); return result; }, [instance] ); return getInstanceProxy(future); }; } return instance.use((v) => v[prop]); } } ); const getStaticProxy = (staticFuture) => new Proxy( {}, { get(_, prop) { if (prop === "then") { return staticFuture.then.bind(staticFuture); } return staticFuture.use((v) => v[prop]); } } ); return new Proxy(Class, { get(target, prop) { if (getTypeOf(target, prop) === "function") { return (...args) => { const future2 = new Future(async () => { const rargs = await Promise.all(args); const result = await target[prop](...rargs); return result; }); return getStaticProxy(future2); }; } const future = new Future(async () => target[prop]); return getStaticProxy(future); }, construct(target, args) { const instance = new Future(async () => { const resolvedArgs = await Promise.all(args); return new target(...resolvedArgs); }); return getInstanceProxy(instance); } }); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { futurifyClass });