"use strict";
/* Socket Lib - Built with esbuild */
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var cache_exports = {};
__export(cache_exports, {
  createTtlCache: () => createTtlCache
});
module.exports = __toCommonJS(cache_exports);
var import_clear = require("../cacache/clear");
var import_read = require("../cacache/read");
var import_write = require("../cacache/write");
var import_date = require("../primordials/date");
var import_error = require("../primordials/error");
var import_json = require("../primordials/json");
var import_map_set = require("../primordials/map-set");
var import_math = require("../primordials/math");
var import_regexp = require("../primordials/regexp");
var import_string = require("../primordials/string");
const DEFAULT_TTL_MS = 5 * 60 * 1e3;
const DEFAULT_PREFIX = "ttl-cache";
const DEFAULT_MEMO_MAX_SIZE = 1e3;
function createTtlCache(options) {
  const opts = {
    __proto__: null,
    memoize: true,
    memoMaxSize: DEFAULT_MEMO_MAX_SIZE,
    prefix: DEFAULT_PREFIX,
    ttl: DEFAULT_TTL_MS,
    ...options
  };
  if (opts.prefix?.includes("*")) {
    throw new import_error.TypeErrorCtor(
      'Cache prefix cannot contain wildcards (*). Use clear({ prefix: "pattern*" }) for wildcard matching.'
    );
  }
  const memoCache = new import_map_set.MapCtor();
  const memoMaxSize = (0, import_math.MathMax)(1, opts.memoMaxSize ?? DEFAULT_MEMO_MAX_SIZE);
  function memoSet(fullKey, entry) {
    if (memoCache.has(fullKey)) {
      memoCache.delete(fullKey);
    } else if (memoCache.size >= memoMaxSize) {
      const oldest = memoCache.keys().next().value;
      if (oldest !== void 0) {
        memoCache.delete(oldest);
      }
    }
    memoCache.set(fullKey, entry);
  }
  const ttl = opts.ttl ?? DEFAULT_TTL_MS;
  function buildKey(key) {
    return `${opts.prefix}:${key}`;
  }
  function isExpired(entry) {
    const now = (0, import_date.DateNow)();
    const maxFutureMs = 1e4;
    if (entry.expiresAt > now + ttl + maxFutureMs) {
      return true;
    }
    return now > entry.expiresAt;
  }
  function createMatcher(pattern) {
    const fullPattern = buildKey(pattern);
    const hasWildcard = pattern.includes("*");
    if (!hasWildcard) {
      return (key) => (0, import_string.StringPrototypeStartsWith)(key, fullPattern);
    }
    const escaped = (0, import_string.StringPrototypeReplaceAll)(
      fullPattern,
      /[.+?^${}()|[\]\\]/g,
      "\\$&"
    );
    const regexPattern = (0, import_string.StringPrototypeReplaceAll)(escaped, "*", ".*");
    const regex = new import_regexp.RegExpCtor(`^${regexPattern}$`);
    return (key) => (0, import_regexp.RegExpPrototypeTest)(regex, key);
  }
  async function get(key) {
    if ((0, import_string.StringPrototypeIncludes)(key, "*")) {
      throw new import_error.TypeErrorCtor(
        "Cache key cannot contain wildcards (*). Use getAll(pattern) to retrieve multiple entries."
      );
    }
    const fullKey = buildKey(key);
    if (opts.memoize) {
      const memoEntry = memoCache.get(fullKey);
      if (memoEntry && !isExpired(memoEntry)) {
        memoSet(fullKey, memoEntry);
        return memoEntry.data;
      }
      if (memoEntry) {
        memoCache.delete(fullKey);
      }
    }
    const cacheEntry = await (0, import_read.safeGet)(fullKey);
    if (cacheEntry) {
      let entry;
      try {
        entry = (0, import_json.JSONParse)(cacheEntry.data.toString("utf8"));
      } catch {
        try {
          await (0, import_write.remove)(fullKey);
        } catch {
        }
        return void 0;
      }
      if (!isExpired(entry)) {
        if (opts.memoize) {
          memoSet(fullKey, entry);
        }
        return entry.data;
      }
      try {
        await (0, import_write.remove)(fullKey);
      } catch {
      }
    }
    return void 0;
  }
  async function getAll(pattern) {
    const results = new import_map_set.MapCtor();
    const matches = createMatcher(pattern);
    if (opts.memoize) {
      for (const [key, entry] of memoCache.entries()) {
        if (!matches(key)) {
          continue;
        }
        if (isExpired(entry)) {
          memoCache.delete(key);
          continue;
        }
        const originalKey = opts.prefix ? (0, import_string.StringPrototypeSlice)(key, opts.prefix.length + 1) : key;
        results.set(originalKey, entry.data);
      }
    }
    const cacheDir = (await import("../paths/socket")).getSocketCacacheDir();
    const cacacheModule = await import("../cacache/_internal");
    const stream = cacacheModule.getCacache().ls.stream(cacheDir);
    for await (const cacheEntry of stream) {
      if (!cacheEntry.key.startsWith(`${opts.prefix}:`)) {
        continue;
      }
      if (!matches(cacheEntry.key)) {
        continue;
      }
      const originalKey = opts.prefix ? cacheEntry.key.slice(opts.prefix.length + 1) : cacheEntry.key;
      if (results.has(originalKey)) {
        continue;
      }
      try {
        const entry = await (0, import_read.safeGet)(cacheEntry.key);
        if (!entry) {
          continue;
        }
        const parsed = (0, import_json.JSONParse)(
          entry.data.toString("utf8")
        );
        if (isExpired(parsed)) {
          await (0, import_write.remove)(cacheEntry.key);
          continue;
        }
        results.set(originalKey, parsed.data);
        if (opts.memoize) {
          memoSet(cacheEntry.key, parsed);
        }
      } catch {
      }
    }
    return results;
  }
  async function set(key, data) {
    if ((0, import_string.StringPrototypeIncludes)(key, "*")) {
      throw new import_error.TypeErrorCtor(
        'Cache key cannot contain wildcards (*). Wildcards are only supported in clear({ prefix: "pattern*" }).'
      );
    }
    const fullKey = buildKey(key);
    const entry = {
      data,
      expiresAt: (0, import_date.DateNow)() + ttl
    };
    if (opts.memoize) {
      memoSet(fullKey, entry);
    }
    try {
      await (0, import_write.put)(fullKey, (0, import_json.JSONStringify)(entry), {
        metadata: { expiresAt: entry.expiresAt }
      });
    } catch {
    }
  }
  const inflightRequests = new import_map_set.MapCtor();
  async function getOrFetch(key, fetcher) {
    const fullKey = buildKey(key);
    const preexisting = inflightRequests.get(fullKey);
    if (preexisting) {
      return await preexisting;
    }
    const cached = await get(key);
    if (cached !== void 0) {
      return cached;
    }
    const rechecked = inflightRequests.get(fullKey);
    if (rechecked) {
      return await rechecked;
    }
    const promise = (async () => {
      try {
        const data = await fetcher();
        await set(key, data);
        return data;
      } finally {
        inflightRequests.delete(fullKey);
      }
    })();
    inflightRequests.set(fullKey, promise);
    return await promise;
  }
  async function deleteEntry(key) {
    if ((0, import_string.StringPrototypeIncludes)(key, "*")) {
      throw new import_error.TypeErrorCtor(
        "Cache key cannot contain wildcards (*). Use deleteAll(pattern) to remove multiple entries."
      );
    }
    const fullKey = buildKey(key);
    memoCache.delete(fullKey);
    try {
      await (0, import_write.remove)(fullKey);
    } catch {
    }
  }
  async function deleteAll(pattern) {
    const fullPrefix = pattern ? `${opts.prefix}:${pattern}` : `${opts.prefix}:`;
    if (!pattern) {
      memoCache.clear();
    } else {
      const matches = createMatcher(pattern);
      for (const key of memoCache.keys()) {
        if (matches(key)) {
          memoCache.delete(key);
        }
      }
    }
    const removed = await (0, import_clear.clear)({ prefix: fullPrefix });
    return removed ?? 0;
  }
  async function clear(options2) {
    const opts2 = { __proto__: null, ...options2 };
    memoCache.clear();
    if (opts2.memoOnly) {
      return;
    }
    await deleteAll();
  }
  return {
    clear,
    delete: deleteEntry,
    deleteAll,
    get,
    getAll,
    getOrFetch,
    set
  };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  createTtlCache
});
