Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/the-system/lazy.ts

Raw
/**
 * Memoize a dynamic import so concurrent callers share one evaluation.
 *
 * Pi loads extensions through jiti with the module cache disabled.
 * Two concurrent imports of the same module can then race: the second
 * caller receives a partially initialized module whose top-level awaits
 * have not finished and whose imported bindings are still `undefined`.
 *
 * Memoize each target and serialize distinct targets, since their shared
 * dependencies can also race through jiti's partially initialized cache.
 * A rejected load clears the memo so the next call retries.
 */
let pending: Promise<unknown> = Promise.resolve();

export function lazy<T>(load: () => Promise<T>): () => Promise<T> {
	let promise: Promise<T> | undefined;
	return () =>
		(promise ??= (() => {
			const next = pending.then(load);
			pending = next.catch(() => {});
			return next.catch((error: unknown) => {
				promise = undefined;
				throw error;
			});
		})());
}