import { createHash } from "node:crypto";
import { isSecret } from "../secret.js";
export function memoize(fn, keyFn = defaultKeyFn) {
    const cache = new Map();
    return async (...args) => {
        const key = keyFn(...args);
        const cached = cache.get(key);
        if (cached) {
            return await cached;
        }
        const promise = fn(...args).catch((error) => {
            cache.delete(key);
            throw error;
        });
        cache.set(key, promise);
        return await promise;
    };
}
/**
 * Single flight memoization.
 * Ensures only one instance of the function is executed at a time.
 * If another instance is already executing, returns the in-flight promise.
 */
export function singleFlight(fn, keyFn = defaultKeyFn) {
    const cache = new Map();
    return async (...args) => {
        const key = keyFn(...args);
        const cached = cache.get(key);
        if (cached) {
            return await cached;
        }
        const promise = fn(...args);
        cache.set(key, promise);
        try {
            return await promise;
        }
        finally {
            cache.delete(key);
        }
    };
}
export function defaultKeyFn(...args) {
    return createHash("sha256")
        .update(JSON.stringify(args, (_, value) => {
        // Secret names may differ between instantiations,
        // so we unwrap it to make the key deterministic.
        if (isSecret(value)) {
            return value.unencrypted;
        }
        return value;
    }))
        .digest("hex");
}
//# sourceMappingURL=memoize.js.map