//#region src/index.ts
/**
* Thin prefix builder. Bump the version segment to bulk-invalidate a keyspace
* (e.g. `namespace('tsi:v1')` → change to `tsi:v2` and old keys miss).
*/
function namespace(prefix) {
	return (key) => `${prefix}:${key}`;
}
function createCache(backend) {
	const inFlight = /* @__PURE__ */ new Map();
	return {
		async get(key) {
			const raw = await backend.get(key);
			if (raw === void 0) return void 0;
			try {
				return JSON.parse(raw);
			} catch {
				return;
			}
		},
		async set(key, value, opts) {
			if (value === void 0) {
				await backend.del(key);
				return;
			}
			await backend.set(key, JSON.stringify(value), opts?.ttl);
		},
		async del(key) {
			await backend.del(key);
		},
		/**
		* Read-through with per-instance single-flight coalescing. Concurrent cold
		* callers on the same key share one loader invocation. In-flight entries are
		* cleared in `finally` so a rejected loader does not poison the key.
		*
		* Coalescing is per runtime instance only — not across isolates or processes.
		*/
		async getOrSet(key, loader, opts) {
			const existing = inFlight.get(key);
			if (existing) return existing;
			const cached = await this.get(key);
			if (cached !== void 0) return cached;
			const racing = inFlight.get(key);
			if (racing) return racing;
			const flight = (async () => {
				try {
					const value = await loader();
					await this.set(key, value, opts);
					return value;
				} finally {
					inFlight.delete(key);
				}
			})();
			inFlight.set(key, flight);
			return flight;
		}
	};
}
//#endregion
export { createCache, namespace };
