(factory: TFactory)
| 9 | type WithInit<TOutput> = TOutput & { init?(...args: any[]): any | Promise<any> }; |
| 10 | |
| 11 | export function Factory<TFactory extends (...args: Parameters<TFactory>) => ReturnType<TFactory>>(factory: TFactory): new (...args: Parameters<TFactory>) => Promise<Awaited<ReturnType<TFactory>>> { |
| 12 | /** calls/awaits any .init in the result from the factory */ |
| 13 | async function initialize(instance: WithInit<ReturnType<TFactory>> | Promise<WithInit<ReturnType<TFactory>>>, args: any[]) { |
| 14 | if (instance !== null && instance !== undefined) { |
| 15 | if (is.promise(instance)) { |
| 16 | instance = await instance; |
| 17 | } |
| 18 | |
| 19 | // if .init is a function, call it, if it's a promise, await it |
| 20 | const pInit = typeof instance.init === 'function' ? instance.init(args) : instance.init; |
| 21 | if (is.promise(pInit)) { |
| 22 | await pInit; |
| 23 | } |
| 24 | } |
| 25 | return instance; |
| 26 | } |
| 27 | |
| 28 | class AsyncFactory extends Promise<ReturnType<TFactory>> { |
| 29 | protected factory: TFactory; |
| 30 | constructor(...args: any[]) { |
| 31 | if (args.length === 1 && typeof args[0] === 'function') { |
| 32 | // this is being called because a new Promise is being created for an async function invocation (not user code) |
| 33 | super(args[0]); |
| 34 | this.factory = factory; |
| 35 | return; |
| 36 | } |
| 37 | |
| 38 | // this is being called because a user is creating an instance of the class, and we want to call the init() method |
| 39 | super((resolve: Resolve<ReturnType<TFactory>>, reject: Reject) => { |
| 40 | try { |
| 41 | // call the factory with the arguments that they provided, then initialize it |
| 42 | initialize(factory(...(args as any)) as any, args).then(resolve).catch(reject); |
| 43 | } catch (error) { |
| 44 | // if the constructor throws, we should reject the promise with that error. |
| 45 | reject(error); |
| 46 | } |
| 47 | }); |
| 48 | this.factory = factory; |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | return AsyncFactory as any as new (...args: Parameters<TFactory>) => Promise<Awaited<ReturnType<TFactory>>>; |
| 53 | } |
no outgoing calls
no test coverage detected