import {Future} from './index.ts' type UnwrapFuture = T extends Future ? U : T extends readonly any[] ? {[K in keyof T]: UnwrapFuture} : T type FuturifyArgs = Params extends [infer Head, ...infer Tail] ? [Head | Future>, ...FuturifyArgs] : [] export type FuturifiedInstance = PromiseLike & { [K in keyof T]: T[K] extends (...args: infer A) => infer R ? (...args: {[P in keyof A]: A[P] | Future}) => FuturifiedInstance> : Future> } type FuturifyFunctionReturn any, R> = R extends InstanceType ? FuturifiedInstance> : Future> type FuturifiedStatic any> = { [K in Exclude]: T[K] extends (...args: infer A) => infer R ? (...args: {[P in keyof A]: A[P] | Future}) => FuturifyFunctionReturn : Future> } export type FuturifiedClass any> = FuturifiedStatic & (new (...args: FuturifyArgs>) => FuturifiedInstance>) function getTypeOf(Class, prop) { try { // Check if the property exists on the class (static members) if (Reflect.has(Class, prop)) { return typeof Class[prop] } // Check if the property exists on the prototype (instance members) if (Reflect.has(Class.prototype, prop)) { return typeof Class.prototype[prop] } return 'undefined' // If the property does not exist } catch (error) { return `Error: ${error.message}` } } // export function futurifyClass any>( // Class: T, // ): FuturifiedClass { // return new Proxy(Class, { // construct(target, args) { // const instance = new Future(async () => { // const resolvedArgs = await Promise.all(args); // return new target(...resolvedArgs); // }); // const getProxy = (instance) => new Proxy({}, { // get(_, prop: keyof InstanceType) { // if (prop === 'then') { // return instance.then.bind(instance) // } // if (getTypeOf(target, prop) === "function") { // return (...args: any[]) => { // const future = new Future(async (resolvedInstance) => { // const rargs = await Promise.all(args) // const result = await resolvedInstance[prop](...rargs) // return result // }, [instance]) // return getProxy(future) // } // } // return instance.use(v => v[prop]) // }, // }); // return getProxy(instance) // }, // }) as unknown as FuturifiedClass // } export function futurifyClass any>(Class: T): FuturifiedClass { const getInstanceProxy = instance => new Proxy( {}, { get(_, prop: keyof InstanceType) { if (prop === 'then') { return instance.then.bind(instance) } if (getTypeOf(Class, prop) === 'function') { return (...args: any[]) => { 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: any[]) => { const future = new Future(async () => { const rargs = await Promise.all(args) const result = await target[prop](...rargs) return result }) return getStaticProxy(future) } } 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) }, }) as unknown as FuturifiedClass }