@leejpsd/nextjs-cache-handler 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/shared/node-require.ts","../src/shared/client/adapter-redis.ts","../src/shared/client/adapter-ioredis.ts","../src/index.ts","../src/cache-components/index.ts","../src/cache-components/handler.ts","../src/shared/abort.ts","../src/shared/compress.ts","../src/shared/client/index.ts","../src/shared/logger.ts","../src/shared/lua/index.ts","../src/shared/lua/set-with-tags.lua","../src/shared/lua/revalidate-hard.lua","../src/shared/lua/refresh-tag-lock.lua","../src/shared/memory-fallback.ts","../src/shared/metrics.ts","../src/shared/namespace.ts","../src/shared/build-phase.ts","../src/cache-components/serialize.ts","../src/cache-components/swr.ts","../src/incremental/index.ts","../src/incremental/handler.ts","../src/incremental/serialize.ts"],"names":["path","adaptRedisV5","createRedisV5Client","adaptIoredis","createIoredisClient","adaptCluster","createIoredisCluster","createIoredisSentinel","DEFAULT_KEY_PREFIX","ENTRY_SUFFIX","TAG_SUFFIX","ONE_YEAR_SEC","DEFAULT_ABORT_MS","gateRedis","init","entryKey"],"mappings":"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","file":"index.js","sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","/**\n * A require() that works from BOTH build outputs.\n *\n * The client/OTel factories load optional peers (`redis`, `ioredis`,\n * `@opentelemetry/api`) lazily at runtime. A bare `require()` compiles fine\n * for CJS but becomes esbuild's `__require` fallback in the ESM build, which\n * throws \"Dynamic require of X is not supported\" in pure-ESM consumers.\n * `createRequire(import.meta.url)` is real in ESM, and tsup's `shims: true`\n * provides an `import.meta.url` polyfill for the CJS build.\n */\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\n\nconst packageRequire = createRequire(import.meta.url);\nconst cwdRequire = createRequire(\n path.join(process.cwd(), \"__resolve-anchor__.js\")\n);\n\nexport function nodeRequire(id: string): unknown {\n try {\n return packageRequire(id);\n } catch {\n // Symlinked installs (npm i <local-path>, pnpm's virtual store) resolve\n // import.meta.url to the package's REAL location, outside the app tree —\n // so peers installed by the app aren't reachable from that anchor. Retry\n // from the process CWD, which under a Next.js server is the app root.\n return cwdRequire(id);\n }\n}\n","/**\n * Adapter for `redis@5` (the official `node-redis` client).\n *\n * v5 already uses camelCase methods that match `RedisClientLike` almost\n * exactly, so this adapter is mostly a type assertion plus the\n * `createRedisV5Client` factory that codifies the \"1.5s connectTimeout,\n * reconnectStrategy: false\" defaults validated in production by the reference\n * implementation.\n */\n\nimport type { RedisClientType } from \"redis\";\n\nimport type { RedisClientConfig, RedisClientLike } from \"../../types.js\";\nimport { nodeRequire } from \"../node-require.js\";\n\nexport function adaptRedisV5(client: RedisClientType): RedisClientLike {\n return client as unknown as RedisClientLike;\n}\n\nexport function createRedisV5Client(\n config: Extract<RedisClientConfig, { type: \"redis\" }>\n): RedisClientType {\n // Lazy require so consumers using ioredis only don't pay the cost.\n // We do `require` instead of `await import` here because the parent\n // `buildClient` is already in an async context that handles awaiting.\n \n const { createClient } = nodeRequire(\"redis\") as typeof import(\"redis\");\n const useTls = config.tls ?? config.url.startsWith(\"rediss://\");\n\n // redis@5 has a discriminated socket union (TCP / TLS / IPC) and disallows\n // explicit `undefined` under exactOptionalPropertyTypes. Build the options\n // object incrementally so optional fields stay absent when not set.\n \n const opts: any = {\n url: config.url,\n socket: {\n connectTimeout: config.connectTimeout ?? 1500,\n reconnectStrategy: false,\n ...(useTls ? { tls: true } : {}),\n },\n };\n if (config.password !== undefined) opts.password = config.password;\n\n return createClient(opts) as RedisClientType;\n}\n","/**\n * Adapter for `ioredis` (and `ioredis.Cluster`).\n *\n * ioredis uses snake_case method names (`sadd`, `smembers`, `mget`) and a\n * stream-based scan. We normalize both into the camelCase / async-iterable\n * `RedisClientLike` contract so the handlers don't need to know which client\n * is underneath.\n */\n\nimport type { Cluster, Redis } from \"ioredis\";\n\nimport type { RedisClientConfig, RedisClientLike } from \"../../types.js\";\nimport { nodeRequire } from \"../node-require.js\";\n\ntype AnyRedis = Redis | Cluster;\n\nfunction adapt(client: AnyRedis, isClusterClient = false): RedisClientLike {\n return {\n get isOpen() {\n // ioredis exposes a `status` string. Both single-node and cluster\n // report \"ready\" once connected.\n return client.status === \"ready\";\n },\n connect: async () => {\n if (client.status !== \"ready\" && client.status !== \"connecting\") {\n await client.connect();\n }\n },\n get: (k) => client.get(k),\n set: (k, v, opts) =>\n opts?.EX !== undefined\n ? client.set(k, v, \"EX\", opts.EX)\n : client.set(k, v),\n del: async (keys) => {\n const arr = Array.isArray(keys) ? keys : [keys];\n if (arr.length === 0) return 0;\n return client.del(...arr);\n },\n sAdd: async (k, m) => {\n const arr = Array.isArray(m) ? m : [m];\n if (arr.length === 0) return 0;\n return client.sadd(k, ...arr);\n },\n sMembers: (k) => client.smembers(k),\n expire: async (k, s) => {\n const r = await client.expire(k, s);\n return r;\n },\n mGet: async (keys) => {\n if (keys.length === 0) return [];\n return client.mget(...keys);\n },\n eval: (script, opts) =>\n client.eval(\n script,\n opts.keys.length,\n ...opts.keys,\n ...opts.arguments\n ) as Promise<unknown>,\n evalSha: (sha, opts) =>\n client.evalsha(\n sha,\n opts.keys.length,\n ...opts.keys,\n ...opts.arguments\n ) as Promise<unknown>,\n scriptLoad: async (script) =>\n (await client.script(\"LOAD\", script)) as string,\n scanIterator: async function* ({ MATCH, COUNT }) {\n // Cluster does not support a single SCAN cursor across slots; use\n // ioredis's per-node iterator there. Single-node: standard SCAN cursor.\n if (isClusterClient) {\n const cluster = client as Cluster;\n for (const node of cluster.nodes(\"master\")) {\n let cursor = \"0\";\n do {\n const [next, batch]: [string, string[]] = await node.scan(\n cursor,\n \"MATCH\",\n MATCH,\n \"COUNT\",\n COUNT ?? 100\n );\n cursor = next;\n if (batch.length > 0) yield batch;\n } while (cursor !== \"0\");\n }\n } else {\n const redis = client as Redis;\n let cursor = \"0\";\n do {\n const [next, batch]: [string, string[]] = await redis.scan(\n cursor,\n \"MATCH\",\n MATCH,\n \"COUNT\",\n COUNT ?? 100\n );\n cursor = next;\n if (batch.length > 0) yield batch;\n } while (cursor !== \"0\");\n }\n },\n ping: () => client.ping(),\n on: (event, listener) => {\n client.on(event, listener);\n return client;\n },\n dispose: () => {\n client.disconnect();\n },\n };\n}\n\nexport function adaptIoredis(client: Redis): RedisClientLike {\n return adapt(client, false);\n}\n\nexport function adaptCluster(cluster: Cluster): RedisClientLike {\n return adapt(cluster, true);\n}\n\nexport function createIoredisClient(\n config: Extract<RedisClientConfig, { type: \"ioredis\" }>\n): Redis {\n \n const IORedis = nodeRequire(\"ioredis\") as typeof import(\"ioredis\");\n // ioredis exports the class as both `default` and a named property.\n // Hitting the default works for both ESM and CJS consumers.\n const Ctor = IORedis.default ?? (IORedis as unknown as typeof import(\"ioredis\").default);\n return new Ctor(config.url, {\n password: config.password,\n connectTimeout: config.connectTimeout ?? 1500,\n tls: config.tls ? {} : undefined,\n lazyConnect: true,\n maxRetriesPerRequest: 1,\n // Batch same-tick commands into one RTT (matches redis@5's default\n // behavior) — makes Promise.all fan-outs a single pipeline.\n enableAutoPipelining: true,\n });\n}\n\nexport function createIoredisSentinel(\n config: Extract<RedisClientConfig, { type: \"sentinel\" }>\n): Redis {\n const IORedis = nodeRequire(\"ioredis\") as typeof import(\"ioredis\");\n const Ctor = IORedis.default ?? (IORedis as unknown as typeof import(\"ioredis\").default);\n return new Ctor({\n sentinels: config.sentinels,\n name: config.name,\n password: config.password,\n sentinelPassword: config.sentinelPassword,\n connectTimeout: config.connectTimeout ?? 1500,\n tls: config.tls ? {} : undefined,\n lazyConnect: true,\n maxRetriesPerRequest: 1,\n enableAutoPipelining: true,\n });\n}\n\nexport function createIoredisCluster(\n config: Extract<RedisClientConfig, { type: \"cluster\" }>\n): Cluster {\n \n const IORedis = nodeRequire(\"ioredis\") as typeof import(\"ioredis\");\n const ClusterCtor =\n IORedis.Cluster ??\n (IORedis.default as unknown as { Cluster: typeof import(\"ioredis\").Cluster })\n .Cluster;\n return new ClusterCtor(config.nodes, {\n redisOptions: {\n password: config.password,\n tls: config.tls ? {} : undefined,\n },\n enableReadyCheck: true,\n lazyConnect: true,\n // Same-slot commands issued in the same tick share one pipeline.\n enableAutoPipelining: true,\n });\n}\n","/**\n * @leejpsd/nextjs-cache-handler — main barrel.\n *\n * Most consumers should import from the dedicated subpath that matches the\n * Next.js option they're configuring:\n *\n * import { createCacheComponentsHandler } from \"@leejpsd/nextjs-cache-handler/cache-components\";\n * import { createIncrementalCacheHandler } from \"@leejpsd/nextjs-cache-handler/incremental\";\n *\n * The root barrel exists so a single `import { ... } from \"@leejpsd/nextjs-cache-handler\"`\n * works for code that wires up both handlers.\n */\n\nexport {\n createCacheComponentsHandler,\n type CacheComponentsHandler,\n partitionEntry,\n shouldServeStale,\n} from \"./cache-components/index.js\";\n\nexport {\n createIncrementalCacheHandler,\n IncrementalRedisCacheHandler,\n type IncrementalCtx,\n} from \"./incremental/index.js\";\n\nexport { CacheTimeoutError } from \"./shared/abort.js\";\nexport { isBuildPhase, shouldUseRedis } from \"./shared/build-phase.js\";\nexport { resolveBuildNamespace } from \"./shared/namespace.js\";\nexport { getMetricSnapshot } from \"./shared/metrics.js\";\n\nexport type {\n CacheHandlerOptions,\n CacheComponentsEntry,\n IncrementalCacheData,\n RedisClientLike,\n RedisClientConfig,\n RedisClientFactory,\n FallbackStrategy,\n MetricEvent,\n MetricEventType,\n MetricEmitter,\n Logger,\n} from \"./types.js\";\n","/**\n * `cacheHandlers` (plural) entry point — for the `'use cache'` directive.\n *\n * Use this from a wrapper module referenced by `next.config.ts`:\n *\n * // cache.config.ts\n * import { createCacheComponentsHandler } from \"@leejpsd/nextjs-cache-handler/cache-components\";\n * module.exports = createCacheComponentsHandler({\n * client: { type: \"redis\", url: process.env.REDIS_URL! },\n * buildNamespace: process.env.DEPLOYMENT_VERSION,\n * });\n *\n * // next.config.ts\n * const nextConfig = {\n * cacheComponents: true,\n * cacheHandlers: {\n * default: require.resolve(\"./cache.config.ts\"),\n * },\n * };\n */\n\nexport {\n createCacheComponentsHandler,\n type CacheComponentsHandler,\n} from \"./handler.js\";\nexport { partitionEntry, shouldServeStale } from \"./swr.js\";\n","/**\n * Spec-compliant `cacheHandlers` (plural) implementation. See docs/next16-spec.md.\n *\n * This module owns the five required methods (`get`, `set`, `refreshTags`,\n * `getExpiration`, `updateTags`) and threads them through:\n * - build-phase short-circuit (src/shared/build-phase.ts)\n * - per-call abort timeout (src/shared/abort.ts)\n * - in-memory fallback when Redis unavailable (src/shared/memory-fallback.ts)\n * - 3-axis SWR partition (./swr.ts)\n * - Lua-atomic SET-with-tags / hard-revalidate (src/shared/lua/)\n *\n * Error policy follows spec §6 verbatim — this module never re-throws on\n * `get` / `set`. `updateTags` with `expire === 0` (hard expire) propagates\n * so the user observes invalidation failures.\n */\n\nimport { CacheTimeoutError, withAbortSignal } from \"../shared/abort.js\";\nimport { compressValue, decompressValue } from \"../shared/compress.js\";\nimport { ConnectionManager } from \"../shared/client/index.js\";\nimport { defaultLogger } from \"../shared/logger.js\";\nimport { execLuaScript } from \"../shared/lua/index.js\";\nimport { MemoryStore, MemorySetStore } from \"../shared/memory-fallback.js\";\nimport { createEmitter } from \"../shared/metrics.js\";\nimport { buildKey, resolveBuildNamespace } from \"../shared/namespace.js\";\nimport { shouldUseRedis } from \"../shared/build-phase.js\";\nimport type {\n CacheComponentsEntry,\n CacheHandlerOptions,\n Logger,\n MetricEmitter,\n RedisClientLike,\n} from \"../types.js\";\n\nimport {\n bufferToStream,\n decodeEnvelope,\n encodeEnvelope,\n readStreamFully,\n} from \"./serialize.js\";\nimport { partitionEntry, shouldServeStale } from \"./swr.js\";\n\n// ─── Defaults / constants ────────────────────────────────────────────────────\n\nconst DEFAULT_KEY_PREFIX = \"next-cache:\";\nconst ENTRY_SUFFIX = \"entry:\";\nconst TAG_SUFFIX = \"tag:\";\nconst TAG_EXP_SUFFIX = \"tag-expiration:\";\nconst LOCK_SUFFIX = \"lock:\";\n\nconst DEFAULT_ABORT_MS = 1500;\nconst DEFAULT_LOCK_TTL_SEC = 10;\n/** When entry.expire === Infinity (the \"never\" sentinel), use this as the\n * Redis EX. One year matches the upstream cap and avoids leaking forever. */\nconst ONE_YEAR_SEC = 60 * 60 * 24 * 365;\n/** Fallback floor when both expire and revalidate are unset/0. */\nconst FALLBACK_TTL_SEC = 3600;\n/** TTL for tag-expiration markers — kept long so cross-deployment readers\n * can still observe an invalidation that happened in the previous deploy. */\nconst TAG_EXP_MARKER_TTL_SEC = 60 * 60 * 24 * 7; // 7 days\n\n// ─── Public factory contract ─────────────────────────────────────────────────\n\nexport interface CacheComponentsHandler {\n get(\n cacheKey: string,\n softTags: string[]\n ): Promise<CacheComponentsEntry | undefined>;\n set(\n cacheKey: string,\n pendingEntry: Promise<CacheComponentsEntry>\n ): Promise<void>;\n refreshTags(): Promise<void>;\n getExpiration(tags: string[]): Promise<number>;\n updateTags(\n tags: string[],\n durations?: { expire?: number }\n ): Promise<void>;\n}\n\n// ─── Implementation ──────────────────────────────────────────────────────────\n\ninterface HandlerState {\n opts: Required<\n Pick<\n CacheHandlerOptions,\n | \"abortTimeoutMs\"\n | \"fallback\"\n | \"staleWhileRevalidate\"\n | \"hashTag\"\n | \"keyPrefix\"\n | \"singleFlight\"\n | \"singleFlightLockTtlSec\"\n >\n > & { rest: CacheHandlerOptions };\n /** Stable instance identifier baked into refresh-lock owner field. Helps\n * operators tell from Redis which task held a given lock. */\n instanceId: string;\n logger: Logger;\n emit: MetricEmitter;\n conn: ConnectionManager;\n /** Memory cache for entries when Redis is unavailable. */\n memEntries: MemoryStore<string>;\n /** Memory tag-set index for memory fallback path. */\n memTags: MemorySetStore;\n /** Memory tag-expiration timestamps. Mirrors next-cache:tag-expiration:*. */\n memTagExp: Map<string, number>;\n /** Local mirror of recent tag invalidations refreshed from Redis. */\n localTagTimestamps: Map<string, number>;\n /** Resolved build namespace, computed once per call. */\n resolveNs: () => string;\n}\n\nfunction gateRedis(state: HandlerState): boolean {\n const fb = state.opts.fallback;\n const ibp = state.opts.rest.isBuildPhase;\n return ibp ? shouldUseRedis({ fallback: fb, isBuildPhase: ibp }) : shouldUseRedis({ fallback: fb });\n}\n\nfunction init(opts: CacheHandlerOptions): HandlerState {\n const logger = opts.logger ?? defaultLogger;\n const emit = createEmitter(opts.onMetric);\n const conn = new ConnectionManager(opts.client, (err) => {\n logger.warn(\"Redis client error\", { message: err.message });\n emit({ type: \"redis.connect.failed\", meta: { message: err.message } });\n });\n\n return {\n opts: {\n abortTimeoutMs: opts.abortTimeoutMs ?? DEFAULT_ABORT_MS,\n fallback: opts.fallback ?? \"auto\",\n staleWhileRevalidate: opts.staleWhileRevalidate ?? true,\n hashTag: opts.hashTag ?? false,\n keyPrefix: opts.keyPrefix ?? DEFAULT_KEY_PREFIX,\n singleFlight: opts.singleFlight ?? false,\n singleFlightLockTtlSec:\n opts.singleFlightLockTtlSec ?? DEFAULT_LOCK_TTL_SEC,\n rest: opts,\n },\n logger,\n emit,\n conn,\n memEntries: new MemoryStore<string>(opts.memoryMaxEntries),\n memTags: new MemorySetStore(opts.memoryMaxEntries),\n memTagExp: new Map(),\n localTagTimestamps: new Map(),\n resolveNs: () => resolveBuildNamespace(opts.buildNamespace),\n instanceId:\n process.env.HOSTNAME ||\n process.env.ECS_TASK_ID ||\n `pid-${process.pid}`,\n };\n}\n\n// ─── Key helpers ─────────────────────────────────────────────────────────────\n\nfunction entryKey(state: HandlerState, cacheKey: string): string {\n return buildKey(\n `${state.opts.keyPrefix}${ENTRY_SUFFIX}`,\n state.resolveNs(),\n cacheKey,\n state.opts.hashTag\n );\n}\n\nfunction tagKey(state: HandlerState, tag: string): string {\n return buildKey(\n `${state.opts.keyPrefix}${TAG_SUFFIX}`,\n state.resolveNs(),\n tag,\n state.opts.hashTag\n );\n}\n\nfunction tagExpKey(state: HandlerState, tag: string): string {\n return buildKey(\n `${state.opts.keyPrefix}${TAG_EXP_SUFFIX}`,\n state.resolveNs(),\n tag,\n state.opts.hashTag\n );\n}\n\nfunction lockKey(state: HandlerState, cacheKey: string): string {\n return buildKey(\n `${state.opts.keyPrefix}${LOCK_SUFFIX}`,\n state.resolveNs(),\n cacheKey,\n state.opts.hashTag\n );\n}\n\n/**\n * Try to acquire the single-flight lock for a stale cache key. Returns true\n * if this instance is the refresh leader, false if someone else already\n * holds the lock or Redis is unavailable.\n *\n * On any error path we return `false` (the safe default — we'd rather miss\n * the leadership signal than block the user response). The lock is purely\n * an observability + stampede-suppression hint; the entry itself is still\n * returned regardless of outcome.\n */\nasync function tryAcquireRefreshLock(\n state: HandlerState,\n cacheKey: string\n): Promise<boolean> {\n if (!state.opts.singleFlight) return false;\n if (!gateRedis(state)) return false;\n\n try {\n return await withAbortSignal(\n \"cacheHandlers.singleFlight.lock\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return false;\n const result = await execLuaScript<number>(\n client,\n \"refreshTagLock\",\n [lockKey(state, cacheKey)],\n [\n state.instanceId,\n String(state.opts.singleFlightLockTtlSec),\n ]\n );\n return result === 1;\n }\n );\n } catch {\n // Best-effort. A failed lock attempt should never block a serve.\n return false;\n }\n}\n\n// ─── TTL resolution ──────────────────────────────────────────────────────────\n\nfunction resolveTtlSeconds(entry: CacheComponentsEntry): number {\n // Per spec §4 cacheLife: expire can be Infinity; map to ONE_YEAR_SEC.\n if (Number.isFinite(entry.expire) && entry.expire > 0) {\n return Math.max(60, Math.ceil(entry.expire));\n }\n if (Number.isFinite(entry.revalidate) && entry.revalidate > 0) {\n return Math.max(60, Math.ceil(entry.revalidate));\n }\n if (entry.expire === Number.POSITIVE_INFINITY) {\n return ONE_YEAR_SEC;\n }\n return FALLBACK_TTL_SEC;\n}\n\n// ─── get() ───────────────────────────────────────────────────────────────────\n\nasync function getImpl(\n state: HandlerState,\n cacheKey: string,\n softTags: string[]\n): Promise<CacheComponentsEntry | undefined> {\n const start = Date.now();\n const useRedis = gateRedis(state);\n\n if (!useRedis && state.opts.fallback === \"never\") {\n state.emit({ type: \"cache.miss\", meta: { reason: \"no-redis\" } });\n return undefined;\n }\n\n const eKey = entryKey(state, cacheKey);\n\n // Try Redis first when allowed.\n let envelope: ReturnType<typeof decodeEnvelope> = null;\n let raw: string | null = null;\n\n if (useRedis) {\n try {\n raw = await withAbortSignal(\n \"cacheHandlers.get\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return null;\n return await client.get(eKey);\n }\n );\n } catch (err) {\n if (err instanceof CacheTimeoutError) {\n state.emit({ type: \"redis.timeout\", meta: { op: \"get\" } });\n } else {\n state.logger.warn(\"get() Redis error, falling back\", {\n message: (err as Error).message,\n });\n }\n raw = null;\n }\n }\n\n if (raw === null && state.opts.fallback !== \"never\") {\n raw = state.memEntries.get(eKey);\n if (raw !== null) state.emit({ type: \"fallback.activated\", meta: { op: \"get\" } });\n }\n\n if (raw === null) {\n state.emit({ type: \"cache.miss\", ms: Date.now() - start });\n return undefined;\n }\n\n try {\n raw = await decompressValue(raw);\n } catch {\n state.emit({ type: \"cache.miss\", meta: { reason: \"decode-error\" } });\n return undefined;\n }\n\n envelope = decodeEnvelope(raw as string);\n if (!envelope) {\n state.emit({ type: \"cache.miss\", meta: { reason: \"decode-error\" } });\n return undefined;\n }\n\n // 3-axis SWR partition.\n const partition = partitionEntry(envelope, Date.now());\n if (!shouldServeStale(partition, state.opts.staleWhileRevalidate)) {\n // Hard miss. Best-effort cleanup of the entry.\n if (useRedis) {\n try {\n await withAbortSignal(\n \"cacheHandlers.get.evict\",\n state.opts.abortTimeoutMs,\n async () => {\n const c = await state.conn.getOrConnect();\n if (c) await c.del(eKey);\n }\n );\n } catch {\n // Ignore — eviction is best-effort.\n }\n } else {\n state.memEntries.delete(eKey);\n }\n state.emit({\n type: \"cache.miss\",\n meta: { reason: \"expired\", freshness: partition.freshness },\n });\n return undefined;\n }\n\n // Soft-tag freshness check. Per spec §2.3#get, an entry is stale if any\n // soft tag was invalidated after entry.timestamp.\n if (softTags.length > 0) {\n let mostRecent = 0;\n for (const t of softTags) {\n const ts = state.localTagTimestamps.get(t);\n if (ts !== undefined && ts > mostRecent) mostRecent = ts;\n }\n if (mostRecent > envelope.timestamp) {\n state.emit({\n type: \"cache.miss\",\n meta: { reason: \"soft-tag-invalidated\" },\n });\n return undefined;\n }\n }\n\n // For stale entries, try the single-flight refresh lock so only one\n // instance triggers the background refresh (when the option is on).\n // The lock outcome is purely informational — we always serve the entry.\n if (partition.freshness === \"stale\") {\n if (state.opts.singleFlight) {\n const isLeader = await tryAcquireRefreshLock(state, cacheKey);\n state.emit({\n type: isLeader\n ? \"cache.stale.refresh.leader\"\n : \"cache.stale.refresh.follower\",\n ms: Date.now() - start,\n meta: { freshness: partition.freshness },\n });\n } else {\n state.emit({\n type: \"cache.stale\",\n ms: Date.now() - start,\n meta: { freshness: partition.freshness },\n });\n }\n } else {\n state.emit({\n type: \"cache.hit\",\n ms: Date.now() - start,\n meta: { freshness: partition.freshness },\n });\n }\n\n // Reconstruct stream and return.\n return {\n value: bufferToStream(Buffer.from(envelope.value, \"base64\")),\n tags: envelope.tags,\n stale: envelope.stale,\n timestamp: envelope.timestamp,\n expire: envelope.expire,\n revalidate: envelope.revalidate,\n };\n}\n\n// ─── set() ───────────────────────────────────────────────────────────────────\n\nasync function setImpl(\n state: HandlerState,\n cacheKey: string,\n pendingEntry: Promise<CacheComponentsEntry>\n): Promise<void> {\n // Spec mandates awaiting the promise before reading value.\n let entry: CacheComponentsEntry;\n try {\n entry = await pendingEntry;\n } catch (err) {\n state.logger.warn(\"pendingEntry rejected, skipping set()\", {\n message: (err as Error).message,\n });\n state.emit({ type: \"cache.set.failed\", meta: { reason: \"pending-rejected\" } });\n return;\n }\n\n let buf: Buffer;\n try {\n buf = await readStreamFully(entry.value);\n } catch (err) {\n // Partial writes — discard per spec §2.3#set.\n state.logger.warn(\"stream errored mid-read, discarding entry\", {\n message: (err as Error).message,\n });\n state.emit({ type: \"cache.set.failed\", meta: { reason: \"partial-stream\" } });\n return;\n }\n\n const eKey = entryKey(state, cacheKey);\n const ttl = resolveTtlSeconds(entry);\n const payload = encodeEnvelope(buf, {\n tags: entry.tags,\n stale: entry.stale,\n timestamp: entry.timestamp,\n expire: entry.expire,\n revalidate: entry.revalidate,\n });\n\n const useRedis = gateRedis(state);\n\n if (!useRedis) {\n state.emit({ type: \"build_phase.skip\", meta: { op: \"set\" } });\n if (state.opts.fallback !== \"never\") {\n state.memEntries.set(eKey, payload, ttl);\n for (const t of entry.tags) {\n state.memTags.sAdd(tagKey(state, t), eKey);\n state.memTags.expire(tagKey(state, t), ttl);\n }\n }\n state.emit({ type: \"cache.set\", meta: { backend: \"memory\" } });\n return;\n }\n\n try {\n await withAbortSignal(\n \"cacheHandlers.set\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) {\n if (state.opts.fallback !== \"never\") {\n state.memEntries.set(eKey, payload, ttl);\n }\n return;\n }\n // Compress only the Redis-bound copy — the memory fallback keeps the\n // plain payload (local reads shouldn't pay decompress CPU).\n const wirePayload = await compressValue(\n payload,\n state.opts.rest.compression\n );\n if (entry.tags.length === 0) {\n // No tags → simple SET.\n await client.set(eKey, wirePayload, { EX: ttl });\n } else {\n await luaSetWithTags(client, state, eKey, wirePayload, ttl, entry.tags);\n }\n }\n );\n state.emit({ type: \"cache.set\", meta: { backend: \"redis\" } });\n } catch (err) {\n if (err instanceof CacheTimeoutError) {\n state.emit({ type: \"redis.timeout\", meta: { op: \"set\" } });\n } else {\n state.logger.warn(\"set() failed (best-effort)\", {\n message: (err as Error).message,\n });\n }\n state.emit({ type: \"cache.set.failed\", meta: { reason: \"redis-error\" } });\n // No re-throw per spec error policy.\n }\n}\n\nasync function luaSetWithTags(\n client: RedisClientLike,\n state: HandlerState,\n eKey: string,\n payload: string,\n ttl: number,\n tags: string[]\n): Promise<void> {\n const tagKeys = tags.map((t) => tagKey(state, t));\n await execLuaScript<number>(\n client,\n \"setWithTags\",\n [eKey, ...tagKeys],\n [payload, String(ttl), String(ttl), String(tags.length)]\n );\n}\n\n// ─── refreshTags() ───────────────────────────────────────────────────────────\n\nasync function refreshTagsImpl(state: HandlerState): Promise<void> {\n // Per spec §6: errors here MUST be caught.\n if (\n !gateRedis(state)\n ) {\n return;\n }\n\n try {\n await withAbortSignal(\n \"cacheHandlers.refreshTags\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return;\n // Scan only the current namespace's markers. The old pattern omitted\n // the namespace, so every deploy's markers were scanned and then\n // discarded by stripExpPrefix; combined with a 500-key cap (SCAN\n // restarts at cursor 0 each call) markers past the cap were never\n // read. Chunk-by-chunk MGET replaces the cap: work per chunk stays\n // small and no marker is silently skipped.\n const ns = state.opts.hashTag\n ? `{${state.resolveNs()}}`\n : state.resolveNs();\n const pattern = `${escapeMatch(\n `${state.opts.keyPrefix}${TAG_EXP_SUFFIX}${ns}:`\n )}*`;\n const scanStartMs = Date.now();\n const fresh = new Map<string, number>();\n for await (const chunk of client.scanIterator({\n MATCH: pattern,\n COUNT: 100,\n })) {\n const keys = Array.isArray(chunk)\n ? chunk.map(String)\n : [String(chunk)];\n if (keys.length === 0) continue;\n const values = await client.mGet(keys);\n for (let i = 0; i < keys.length; i += 1) {\n const v = values[i];\n if (!v) continue;\n const ts = Number.parseInt(v, 10);\n if (!Number.isFinite(ts)) continue;\n // Strip prefix back to bare tag name.\n const key = keys[i];\n if (key === undefined) continue;\n const tag = stripExpPrefix(state, key);\n if (tag) fresh.set(tag, ts);\n }\n }\n // Invalidations recorded locally while the scan ran may not have had\n // visible markers yet — carry them over so they aren't lost.\n for (const [tag, ts] of state.localTagTimestamps) {\n if (ts >= scanStartMs && (fresh.get(tag) ?? 0) < ts) {\n fresh.set(tag, ts);\n }\n }\n // Wholesale replacement keeps the mirror bounded by live-marker\n // count: tags whose markers expired out of Redis (7d TTL) drop out\n // here. Only reached on a complete scan — a failed or timed-out scan\n // keeps the previous mirror instead of installing partial data.\n state.localTagTimestamps = fresh;\n }\n );\n } catch (err) {\n state.logger.warn(\"refreshTags() error swallowed\", {\n message: (err as Error).message,\n });\n }\n}\n\n/** Escape Redis MATCH glob metacharacters so key prefixes match literally. */\nfunction escapeMatch(s: string): string {\n return s.replace(/[\\\\*?[\\]]/g, \"\\\\$&\");\n}\n\n/** Cap for the process-local tag-timestamp mirrors. */\nconst MAX_LOCAL_TAG_ENTRIES = 10_000;\n\n/** Drop the oldest-timestamped entries until the map fits the cap. */\nfunction pruneOldestByTimestamp(\n map: Map<string, number>,\n maxEntries: number\n): void {\n if (map.size <= maxEntries) return;\n const byAge = [...map.entries()].sort((a, b) => a[1] - b[1]);\n const drop = map.size - maxEntries;\n for (let i = 0; i < drop; i += 1) {\n const entry = byAge[i];\n if (entry) map.delete(entry[0]);\n }\n}\n\nfunction stripExpPrefix(state: HandlerState, fullKey: string): string | null {\n const ns = state.resolveNs();\n const prefix = state.opts.hashTag\n ? `${state.opts.keyPrefix}${TAG_EXP_SUFFIX}{${ns}}:`\n : `${state.opts.keyPrefix}${TAG_EXP_SUFFIX}${ns}:`;\n return fullKey.startsWith(prefix) ? fullKey.slice(prefix.length) : null;\n}\n\n// ─── getExpiration() ────────────────────────────────────────────────────────\n\nasync function getExpirationImpl(\n state: HandlerState,\n tags: string[]\n): Promise<number> {\n if (tags.length === 0) return 0;\n\n let max = 0;\n for (const t of tags) {\n const local = state.localTagTimestamps.get(t);\n if (local !== undefined && local > max) max = local;\n const mem = state.memTagExp.get(t);\n if (mem !== undefined && mem > max) max = mem;\n }\n if (max > 0) {\n state.emit({ type: \"tag.expiration.read\", meta: { source: \"local\", count: tags.length } });\n return max;\n }\n\n // Cold path: no local hits → consult Redis if reachable.\n if (\n !gateRedis(state)\n ) {\n return 0;\n }\n\n try {\n return await withAbortSignal(\n \"cacheHandlers.getExpiration\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return 0;\n const keys = tags.map((t) => tagExpKey(state, t));\n const values = await client.mGet(keys);\n let m = 0;\n for (const v of values) {\n if (!v) continue;\n const n = Number.parseInt(v, 10);\n if (Number.isFinite(n) && n > m) m = n;\n }\n return m;\n }\n );\n } catch {\n // Best-effort. Falling back to 0 is safe (treats tags as never invalidated).\n return 0;\n }\n}\n\n// ─── updateTags() ───────────────────────────────────────────────────────────\n\nasync function updateTagsImpl(\n state: HandlerState,\n tags: string[],\n durations?: { expire?: number }\n): Promise<void> {\n if (tags.length === 0) return;\n const isHardExpire = durations?.expire === 0;\n const now = Date.now();\n\n // Local mirror update first — guarantees read-after-write within instance.\n for (const t of tags) {\n state.localTagTimestamps.set(t, now);\n state.memTagExp.set(t, now);\n }\n // memTagExp has no scan-based rebuild to shed dead tags (refreshTags only\n // replaces localTagTimestamps), so cap it here against unbounded growth in\n // high-tag-cardinality apps.\n pruneOldestByTimestamp(state.memTagExp, MAX_LOCAL_TAG_ENTRIES);\n\n if (\n !gateRedis(state)\n ) {\n if (isHardExpire) {\n // Drop matching entries from memory.\n for (const t of tags) {\n const tk = tagKey(state, t);\n const members = state.memTags.sMembers(tk);\n for (const m of members) state.memEntries.delete(m);\n state.memTags.delete(tk);\n }\n }\n state.emit({\n type: isHardExpire ? \"tag.invalidate.hard\" : \"tag.invalidate.soft\",\n meta: { count: tags.length, backend: \"memory\" },\n });\n return;\n }\n\n // Soft path: best-effort. Hard path: propagate failure.\n try {\n await withAbortSignal(\n \"cacheHandlers.updateTags\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) {\n if (isHardExpire) {\n throw new Error(\n \"[next-cache] hard updateTags requested but Redis unavailable\"\n );\n }\n return;\n }\n // Concurrent fan-out instead of a per-tag await chain: N tags cost\n // ~1 round trip (redis@5 auto-pipelines same-tick commands; ioredis\n // has enableAutoPipelining set in our factory) instead of N. With\n // many tags the sequential version could exceed abortTimeoutMs.\n await Promise.all(\n tags.map((t) =>\n isHardExpire\n ? execLuaScript<number>(\n client,\n \"revalidateHard\",\n [tagKey(state, t), tagExpKey(state, t)],\n [String(now), String(TAG_EXP_MARKER_TTL_SEC)]\n )\n : client.set(tagExpKey(state, t), String(now), {\n EX: TAG_EXP_MARKER_TTL_SEC,\n })\n )\n );\n }\n );\n state.emit({\n type: isHardExpire ? \"tag.invalidate.hard\" : \"tag.invalidate.soft\",\n meta: { count: tags.length, backend: \"redis\" },\n });\n } catch (err) {\n if (err instanceof CacheTimeoutError) {\n state.emit({ type: \"redis.timeout\", meta: { op: \"updateTags\" } });\n }\n if (isHardExpire) {\n // Hard failures must surface — read-your-own-writes was requested.\n throw err;\n }\n state.logger.warn(\"updateTags() soft path failed (best-effort)\", {\n message: (err as Error).message,\n });\n }\n}\n\n// ─── Public factory ─────────────────────────────────────────────────────────\n\nexport function createCacheComponentsHandler(\n opts: CacheHandlerOptions\n): CacheComponentsHandler {\n const state = init(opts);\n return {\n get: (cacheKey, softTags) => getImpl(state, cacheKey, softTags),\n set: (cacheKey, pendingEntry) => setImpl(state, cacheKey, pendingEntry),\n refreshTags: () => refreshTagsImpl(state),\n getExpiration: (tags) => getExpirationImpl(state, tags),\n updateTags: (tags, durations) => updateTagsImpl(state, tags, durations),\n };\n}\n","/**\n * Timeout-bounded operation wrapper. Surrounds every Redis call so a hung\n * connection doesn't lock up the Next.js request thread.\n *\n * Why explicit `withAbortSignal` instead of a Proxy (like @fortedigital's\n * `withAbortSignalProxy`):\n * - Stack traces stay clean; consumers see \"cacheHandlers.get\" not \"Proxy.apply\"\n * - Per-method timeouts can differ (set 500ms, updateTags 3000ms) without\n * re-instantiating a Proxy\n * - Easier to follow in `step into` debugging\n */\n\nexport class CacheTimeoutError extends Error {\n override readonly name = \"CacheTimeoutError\";\n constructor(\n public readonly opName: string,\n public readonly ms: number\n ) {\n super(`[@leejpsd/nextjs-cache-handler] ${opName} timed out after ${ms}ms`);\n }\n}\n\n/**\n * Run `fn` with a hard deadline. The provided AbortSignal is forwarded so the\n * inner operation can cancel cooperatively if it supports it.\n *\n * Behavior:\n * - If `fn` resolves before the deadline → resolved value is returned\n * - If the deadline fires first → CacheTimeoutError is thrown\n *\n * Note: aborting the AbortSignal does NOT close the underlying Redis socket.\n * The connection is retained for subsequent calls. We trust the Redis client\n * to recover on its own; we just stop waiting on this particular promise.\n */\nexport async function withAbortSignal<T>(\n opName: string,\n ms: number,\n fn: (signal: AbortSignal) => Promise<T>\n): Promise<T> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), ms);\n if (typeof timer === \"object\" && \"unref\" in timer) {\n // Don't keep the event loop alive just for this timer.\n (timer as { unref: () => void }).unref();\n }\n\n try {\n const timeoutPromise = new Promise<never>((_, reject) => {\n const onAbort = () => {\n ctrl.signal.removeEventListener(\"abort\", onAbort);\n reject(new CacheTimeoutError(opName, ms));\n };\n if (ctrl.signal.aborted) onAbort();\n else ctrl.signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n\n return await Promise.race([fn(ctrl.signal), timeoutPromise]);\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * Transparent value compression for Redis-bound entries (node:zlib — zero\n * added dependencies).\n *\n * Storage format: `<marker><base64>` with marker `__ncgz__:` (gzip) or\n * `__ncbr__:` (brotli). Values without a marker pass through untouched, so\n * mixed caches stay readable: entries written before compression was enabled,\n * or by instances configured differently, decode fine — decompression is\n * always active regardless of the local `compression` option.\n *\n * Base64 re-inflates the compressed bytes by ~33% (our client contract is\n * string-typed), but RSC/HTML payloads are text-heavy enough that the net\n * reduction is typically 3–5×. Payloads under 1 KiB are stored uncompressed —\n * at that size marker+header overhead can exceed the savings.\n *\n * Only entry values are compressed. Tag markers and tag states are a few\n * bytes each and stay plain.\n */\n\nimport { promisify } from \"node:util\";\nimport {\n brotliCompress,\n brotliDecompress,\n constants,\n gunzip,\n gzip,\n} from \"node:zlib\";\n\nconst gzipAsync = promisify(gzip);\nconst gunzipAsync = promisify(gunzip);\nconst brotliCompressAsync = promisify(brotliCompress);\nconst brotliDecompressAsync = promisify(brotliDecompress);\n\nexport type CompressionAlgo = \"gzip\" | \"brotli\";\n\nconst GZIP_MARKER = \"__ncgz__:\";\nconst BROTLI_MARKER = \"__ncbr__:\";\nconst MIN_COMPRESS_BYTES = 1024;\n\n/**\n * Brotli's default quality (11) is tuned for static assets and is far too\n * slow for a request-path cache write. 5 compresses close to gzip speed\n * while still beating it on ratio for text.\n */\nconst BROTLI_OPTS = {\n params: { [constants.BROTLI_PARAM_QUALITY]: 5 },\n};\n\nexport async function compressValue(\n value: string,\n algo: CompressionAlgo | undefined\n): Promise<string> {\n if (!algo || Buffer.byteLength(value) < MIN_COMPRESS_BYTES) return value;\n const input = Buffer.from(value);\n if (algo === \"gzip\") {\n return GZIP_MARKER + (await gzipAsync(input)).toString(\"base64\");\n }\n return (\n BROTLI_MARKER +\n (await brotliCompressAsync(input, BROTLI_OPTS)).toString(\"base64\")\n );\n}\n\n/**\n * Marker-dispatched decompression. Unmarked values are returned as-is.\n * Throws on corrupt compressed data — callers treat that as a cache miss.\n */\nexport async function decompressValue(\n value: string | null\n): Promise<string | null> {\n if (value === null) return null;\n if (value.startsWith(GZIP_MARKER)) {\n const buf = Buffer.from(value.slice(GZIP_MARKER.length), \"base64\");\n return (await gunzipAsync(buf)).toString(\"utf8\");\n }\n if (value.startsWith(BROTLI_MARKER)) {\n const buf = Buffer.from(value.slice(BROTLI_MARKER.length), \"base64\");\n return (await brotliDecompressAsync(buf)).toString(\"utf8\");\n }\n return value;\n}\n","/**\n * Client factory. Resolves a `RedisClientFactory | RedisClientConfig` to a\n * connected `RedisClientLike`, with idempotent connect.\n *\n * The factory caches the resolved client per-handler so repeated calls don't\n * spawn parallel connections. Adapter modules (`adapter-redis`,\n * `adapter-ioredis`) are lazy-imported so peer-deps you don't use stay out of\n * your bundle.\n */\n\nimport type {\n RedisClientFactory,\n RedisClientConfig,\n RedisClientLike,\n} from \"../../types.js\";\n\nexport async function buildClient(\n source: RedisClientFactory | RedisClientConfig\n): Promise<RedisClientLike> {\n if (typeof source === \"function\") {\n return await source();\n }\n switch (source.type) {\n case \"redis\": {\n const { adaptRedisV5, createRedisV5Client } = await import(\n \"./adapter-redis.js\"\n );\n return adaptRedisV5(createRedisV5Client(source));\n }\n case \"ioredis\": {\n const { adaptIoredis, createIoredisClient } = await import(\n \"./adapter-ioredis.js\"\n );\n return adaptIoredis(createIoredisClient(source));\n }\n case \"cluster\": {\n const { adaptCluster, createIoredisCluster } = await import(\n \"./adapter-ioredis.js\"\n );\n return adaptCluster(createIoredisCluster(source));\n }\n case \"sentinel\": {\n const { adaptIoredis, createIoredisSentinel } = await import(\n \"./adapter-ioredis.js\"\n );\n return adaptIoredis(createIoredisSentinel(source));\n }\n default: {\n const exhaustive: never = source;\n throw new Error(\n `[next-cache] unknown client config: ${JSON.stringify(exhaustive)}`\n );\n }\n }\n}\n\nexport interface ConnectionRetryOptions {\n /** Cooldown before the first retry after a failed connect (ms). Default 1000. */\n baseCooldownMs?: number;\n /** Upper bound for the exponential cooldown (ms). Default 30000. */\n maxCooldownMs?: number;\n}\n\n/**\n * Manage connect state without launching parallel connect calls. The reference\n * implementation's `connectPromise` pattern is preserved here.\n *\n * A failed connect does NOT latch the manager into a dead state: retries are\n * allowed after an exponential cooldown (base 1s, doubling per consecutive\n * failure, capped at 30s). During the cooldown `getOrConnect()` returns `null`\n * immediately so request paths fast-fail to the memory fallback instead of\n * queueing behind doomed connect attempts. A dropped connection (client\n * present but no longer open) is replaced with a fresh client on the next\n * call; the dead client is disposed best-effort.\n */\nexport class ConnectionManager {\n private client: RedisClientLike | null = null;\n private connecting: Promise<RedisClientLike | null> | null = null;\n private consecutiveFailures = 0;\n private lastFailureAt = 0;\n private readonly baseCooldownMs: number;\n private readonly maxCooldownMs: number;\n\n constructor(\n private readonly source: RedisClientFactory | RedisClientConfig,\n private readonly onError: (err: Error) => void,\n retry: ConnectionRetryOptions = {}\n ) {\n this.baseCooldownMs = retry.baseCooldownMs ?? 1000;\n this.maxCooldownMs = retry.maxCooldownMs ?? 30_000;\n }\n\n private cooldownMs(): number {\n if (this.consecutiveFailures === 0) return 0;\n return Math.min(\n this.maxCooldownMs,\n this.baseCooldownMs * 2 ** (this.consecutiveFailures - 1)\n );\n }\n\n async getOrConnect(): Promise<RedisClientLike | null> {\n if (this.client?.isOpen) return this.client;\n if (this.connecting) return this.connecting;\n if (Date.now() - this.lastFailureAt < this.cooldownMs()) return null;\n\n const stale = this.client;\n this.client = null;\n\n this.connecting = (async () => {\n disposeQuietly(stale);\n try {\n const c = await buildClient(this.source);\n c.on(\"error\", (err) => this.onError(err));\n if (!c.isOpen) await c.connect();\n this.client = c;\n this.consecutiveFailures = 0;\n return c;\n } catch (err) {\n this.consecutiveFailures += 1;\n this.lastFailureAt = Date.now();\n this.onError(err as Error);\n return null;\n } finally {\n this.connecting = null;\n }\n })();\n\n return this.connecting;\n }\n\n reset(): void {\n disposeQuietly(this.client);\n this.client = null;\n this.connecting = null;\n this.consecutiveFailures = 0;\n this.lastFailureAt = 0;\n }\n}\n\n/**\n * Close a replaced client so it stops reconnect loops and frees its socket.\n * The adapters expose `dispose`; raw clients passed via a factory may expose\n * `destroy` (redis@5) or `disconnect` (ioredis) instead.\n */\nfunction disposeQuietly(client: RedisClientLike | null): void {\n if (!client) return;\n const c = client as RedisClientLike & {\n destroy?: () => unknown;\n disconnect?: () => unknown;\n };\n try {\n (c.dispose ?? c.destroy ?? c.disconnect)?.call(c);\n } catch {\n // Best-effort: a client that fails to close is abandoned to GC.\n }\n}\n","/**\n * Default logger — `console`-backed at warn level and above. Keeps `info` /\n * `debug` quiet so the cache layer doesn't pollute production logs by default.\n *\n * Apps that want verbose tracing inject their own `Logger` via\n * `CacheHandlerOptions.logger`.\n */\n\nimport type { Logger } from \"../types.js\";\n\nexport const defaultLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: (message, meta) => {\n if (meta) console.warn(`[next-cache] ${message}`, meta);\n else console.warn(`[next-cache] ${message}`);\n },\n error: (message, meta) => {\n if (meta) console.error(`[next-cache] ${message}`, meta);\n else console.error(`[next-cache] ${message}`);\n },\n};\n","/**\n * Lua script loader. Handles the EVALSHA → NOSCRIPT → SCRIPT LOAD → EVALSHA\n * dance so the network round-trip cost is one packet on every call after the\n * first.\n *\n * The script bodies are imported as strings via tsup's `loader: { '.lua':\n * 'text' }` configuration. We compute their SHA1 lazily on first use rather\n * than pre-loading on connect — a connect handler that pre-loads scripts adds\n * a startup failure mode (Redis ACLs that block SCRIPT LOAD will surface as\n * connection errors) without a corresponding benefit.\n */\n\nimport { createHash } from \"node:crypto\";\n\nimport type { RedisClientLike } from \"../../types.js\";\n\nimport setWithTagsLua from \"./set-with-tags.lua\";\nimport revalidateHardLua from \"./revalidate-hard.lua\";\nimport refreshTagLockLua from \"./refresh-tag-lock.lua\";\n\nexport const SCRIPTS = {\n setWithTags: setWithTagsLua,\n revalidateHard: revalidateHardLua,\n refreshTagLock: refreshTagLockLua,\n} as const;\n\nexport type ScriptName = keyof typeof SCRIPTS;\n\nconst shaCache = new Map<ScriptName, string>();\n\nfunction sha1(body: string): string {\n return createHash(\"sha1\").update(body).digest(\"hex\");\n}\n\nfunction isNoScriptError(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n const msg = (err as { message?: string }).message ?? \"\";\n return msg.includes(\"NOSCRIPT\");\n}\n\n/**\n * Execute a named Lua script with EVALSHA, falling back to EVAL + SCRIPT LOAD\n * if the server doesn't have it cached (e.g. Redis was restarted).\n */\nexport async function execLuaScript<TResult = unknown>(\n client: RedisClientLike,\n name: ScriptName,\n keys: string[],\n args: string[]\n): Promise<TResult> {\n const body = SCRIPTS[name];\n let cachedSha = shaCache.get(name);\n if (cachedSha === undefined) {\n cachedSha = sha1(body);\n shaCache.set(name, cachedSha);\n }\n\n // Best path: EVALSHA. Most Redis servers will have the script cached after\n // the first EVAL.\n if (typeof client.evalSha === \"function\") {\n try {\n return (await client.evalSha(cachedSha, {\n keys,\n arguments: args,\n })) as TResult;\n } catch (err) {\n if (!isNoScriptError(err)) {\n // Some other failure — propagate.\n throw err;\n }\n // Fall through to EVAL.\n }\n }\n\n // EVAL ships the script body and primes the server cache. Subsequent\n // EVALSHA on this connection will succeed.\n return (await client.eval(body, { keys, arguments: args })) as TResult;\n}\n","-- set-with-tags.lua\n--\n-- Atomically write a cache entry and update the tag indices that point at it.\n-- Replaces the non-atomic SET → SADD → EXPIRE sequence in the reference\n-- implementation, which had a race window where another instance's hard\n-- invalidate could leave dangling tag members.\n--\n-- KEYS[1] : entry key (e.g. \"next-cache:entry:abc123\")\n-- KEYS[2..N] : tag set keys (e.g. \"next-cache:tag:posts\")\n-- ARGV[1] : serialized entry payload\n-- ARGV[2] : entry TTL in seconds\n-- ARGV[3] : tag TTL in seconds (typically same as entry TTL)\n-- ARGV[4] : tag count (number of KEYS after KEYS[1])\n--\n-- Returns: 1 on success.\n\nlocal entryKey = KEYS[1]\nlocal payload = ARGV[1]\nlocal entryTtl = tonumber(ARGV[2])\nlocal tagTtl = tonumber(ARGV[3])\nlocal tagCount = tonumber(ARGV[4])\n\nredis.call('SET', entryKey, payload, 'EX', entryTtl)\n\nfor i = 1, tagCount do\n local tagKey = KEYS[i + 1]\n redis.call('SADD', tagKey, entryKey)\n -- EXPIRE on every SADD: ensures the tag set never outlives its entries\n -- and survives at least as long as the longest associated entry.\n redis.call('EXPIRE', tagKey, tagTtl)\nend\n\nreturn 1\n","-- revalidate-hard.lua\n--\n-- Atomically remove every entry referenced by a tag and stamp the tag's\n-- expiration marker. Used by `updateTags(tags, { expire: 0 })` — the hard\n-- invalidation path triggered by `updateTag()` server actions in Next.js 16.\n--\n-- KEYS[1] : tag set key (e.g. \"next-cache:tag:posts\")\n-- KEYS[2] : tag-expiration marker key (e.g. \"next-cache:tag-expiration:posts\")\n-- ARGV[1] : current timestamp in milliseconds\n-- ARGV[2] : marker TTL in seconds (default: 1 day so cross-deployment\n-- readers can still observe the invalidation)\n--\n-- Returns: number of entries that were deleted.\n\nlocal tagKey = KEYS[1]\nlocal markerKey = KEYS[2]\nlocal nowMs = ARGV[1]\nlocal markerTtl = tonumber(ARGV[2])\n\nlocal entries = redis.call('SMEMBERS', tagKey)\nlocal deleted = 0\n\nif #entries > 0 then\n -- DEL accepts varargs; unpack the entry list.\n redis.call('DEL', unpack(entries))\n deleted = #entries\nend\n\n-- Drop the tag set itself; on next SET it'll be recreated by set-with-tags.\nredis.call('DEL', tagKey)\n\n-- Stamp the invalidation timestamp. Readers compare this against an entry's\n-- timestamp inside `getExpiration` to decide whether soft-tag-only entries\n-- should be considered stale.\nredis.call('SET', markerKey, nowMs, 'EX', markerTtl)\n\nreturn deleted\n","-- refresh-tag-lock.lua\n--\n-- Single-flight lock acquisition for background refresh.\n-- Reserved for v0.2's stampede-protection feature. Currently unused by the\n-- handler runtime, but bundled so v0.2 can ship without a major bump.\n--\n-- KEYS[1] : lock key (e.g. \"next-cache:lock:abc123\")\n-- ARGV[1] : owner identifier (instance id; written for observability)\n-- ARGV[2] : lock TTL in seconds (10s recommended — long enough for refresh\n-- to complete, short enough to recover from a crashed owner)\n--\n-- Returns: 1 if lock acquired, 0 if another owner already holds it.\n\nlocal lockKey = KEYS[1]\nlocal owner = ARGV[1]\nlocal ttl = tonumber(ARGV[2])\n\nif redis.call('GET', lockKey) then\n return 0\nend\n\nredis.call('SET', lockKey, owner, 'EX', ttl)\nreturn 1\n","/**\n * In-memory cache stores with proper TTL handling.\n *\n * The reference implementation in next-redis-cache-demo had a subtle leak:\n * when the memory fallback was activated, `getMemoryTagSet(tag).add(redisKey)`\n * stored entries indefinitely because no `setTimeout` was registered to clean\n * them up. This implementation fixes that by attaching an `unref()`-ed timer\n * to every keyed value.\n *\n * Why two classes:\n * - `MemoryStore<T>` mirrors Redis SET/GET/DEL with EX semantics\n * - `MemorySetStore` mirrors SADD/SMEMBERS/EXPIRE for tag indices\n */\n\ninterface MemoryEntry<T> {\n value: T;\n expiresAt: number;\n}\n\n/**\n * Node's setTimeout coerces delays to a 32-bit signed integer. Anything\n * beyond ~24.85 days fires immediately with a TimeoutOverflowWarning. We cap\n * scheduled timers at this safe maximum and rely on the lazy `expiresAt`\n * check inside `get()` for the rest. Useful for the 1-year TTL fallback that\n * `cacheLife({expire: Infinity})` resolves to.\n */\nconst MAX_TIMER_MS = 2_147_483_647; // 2^31 - 1, ~24.85 days\nfunction clampTimerMs(ms: number): number {\n return Math.min(Math.max(0, ms), MAX_TIMER_MS);\n}\n\n/**\n * Default entry cap for the fallback stores. The fallback exists to ride out\n * a Redis outage, not to replace it — an unbounded map filled by a long\n * outage on a busy site is an OOM waiting to happen.\n */\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport class MemoryStore<T> {\n private readonly kv = new Map<string, MemoryEntry<T>>();\n private readonly timers = new Map<string, ReturnType<typeof setTimeout>>();\n private readonly maxEntries: number;\n\n constructor(maxEntries: number = DEFAULT_MAX_ENTRIES) {\n this.maxEntries = Math.max(1, maxEntries);\n }\n\n set(key: string, value: T, ttlSeconds: number): void {\n this.delete(key);\n const expiresAt = Date.now() + ttlSeconds * 1000;\n this.kv.set(key, { value, expiresAt });\n const timer = setTimeout(() => this.delete(key), clampTimerMs(ttlSeconds * 1000));\n if (typeof timer === \"object\" && \"unref\" in timer) {\n (timer as { unref: () => void }).unref();\n }\n this.timers.set(key, timer);\n // LRU eviction: Map preserves insertion order and get() re-inserts on\n // hit, so the first key is always the least recently used.\n while (this.kv.size > this.maxEntries) {\n const oldest = this.kv.keys().next().value as string;\n this.delete(oldest);\n }\n }\n\n get(key: string): T | null {\n const entry = this.kv.get(key);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n this.delete(key);\n return null;\n }\n // Refresh recency for LRU ordering.\n this.kv.delete(key);\n this.kv.set(key, entry);\n return entry.value;\n }\n\n delete(key: string): boolean {\n const timer = this.timers.get(key);\n if (timer !== undefined) {\n clearTimeout(timer);\n this.timers.delete(key);\n }\n return this.kv.delete(key);\n }\n\n has(key: string): boolean {\n return this.get(key) !== null;\n }\n\n keys(): string[] {\n const now = Date.now();\n const live: string[] = [];\n for (const [key, entry] of this.kv.entries()) {\n if (entry.expiresAt >= now) live.push(key);\n }\n return live;\n }\n\n size(): number {\n return this.keys().length;\n }\n\n clear(): void {\n for (const timer of this.timers.values()) clearTimeout(timer);\n this.timers.clear();\n this.kv.clear();\n }\n}\n\n/**\n * Set-of-strings store with per-set TTL. Mirrors Redis SADD / SMEMBERS / EXPIRE.\n *\n * TTL semantics: EXPIRE replaces the previous TTL. We schedule one timer per\n * set (not per member) and reset it on every SADD or EXPIRE.\n */\nexport class MemorySetStore {\n private readonly sets = new Map<string, Set<string>>();\n private readonly expiresAt = new Map<string, number>();\n private readonly timers = new Map<string, ReturnType<typeof setTimeout>>();\n private readonly maxSets: number;\n\n constructor(maxSets: number = DEFAULT_MAX_ENTRIES) {\n this.maxSets = Math.max(1, maxSets);\n }\n\n sAdd(key: string, member: string | string[]): number {\n const members = Array.isArray(member) ? member : [member];\n let set = this.sets.get(key);\n if (!set) {\n set = new Set();\n } else {\n // Refresh recency for LRU ordering.\n this.sets.delete(key);\n }\n this.sets.set(key, set);\n let added = 0;\n for (const m of members) {\n if (!set.has(m)) {\n set.add(m);\n added += 1;\n }\n }\n while (this.sets.size > this.maxSets) {\n const oldest = this.sets.keys().next().value as string;\n this.delete(oldest);\n }\n return added;\n }\n\n sMembers(key: string): string[] {\n if (this.isExpired(key)) {\n this.delete(key);\n return [];\n }\n const set = this.sets.get(key);\n return set ? Array.from(set) : [];\n }\n\n expire(key: string, ttlSeconds: number): boolean {\n if (!this.sets.has(key)) return false;\n const prev = this.timers.get(key);\n if (prev !== undefined) clearTimeout(prev);\n const expiresAt = Date.now() + ttlSeconds * 1000;\n this.expiresAt.set(key, expiresAt);\n const timer = setTimeout(() => this.delete(key), clampTimerMs(ttlSeconds * 1000));\n if (typeof timer === \"object\" && \"unref\" in timer) {\n (timer as { unref: () => void }).unref();\n }\n this.timers.set(key, timer);\n return true;\n }\n\n delete(key: string): boolean {\n const timer = this.timers.get(key);\n if (timer !== undefined) {\n clearTimeout(timer);\n this.timers.delete(key);\n }\n this.expiresAt.delete(key);\n return this.sets.delete(key);\n }\n\n keys(): string[] {\n const live: string[] = [];\n for (const key of this.sets.keys()) {\n if (!this.isExpired(key)) live.push(key);\n }\n return live;\n }\n\n clear(): void {\n for (const timer of this.timers.values()) clearTimeout(timer);\n this.timers.clear();\n this.expiresAt.clear();\n this.sets.clear();\n }\n\n private isExpired(key: string): boolean {\n const at = this.expiresAt.get(key);\n return at !== undefined && Date.now() > at;\n }\n}\n","/**\n * Process-local metric counters with an optional emit hook.\n *\n * Two layers:\n * 1. Always-on counter accumulation (free for app-side `getMetricSnapshot()`)\n * 2. Optional `onMetric` callback for OpenTelemetry / StatsD / Datadog\n * forwarding (no transitive deps in this package)\n *\n * Cardinality discipline: callers pass low-cardinality `meta` (e.g. operation\n * name, freshness bucket). Cache keys and tag names are never emitted.\n */\n\nimport type { MetricEmitter, MetricEvent, MetricEventType } from \"../types.js\";\n\ninterface Counter {\n count: number;\n totalMs: number;\n lastTs: number;\n}\n\nconst counters = new Map<MetricEventType, Counter>();\n\nfunction bump(event: MetricEvent): void {\n const existing = counters.get(event.type);\n if (existing) {\n existing.count += 1;\n if (event.ms !== undefined) existing.totalMs += event.ms;\n existing.lastTs = Date.now();\n return;\n }\n counters.set(event.type, {\n count: 1,\n totalMs: event.ms ?? 0,\n lastTs: Date.now(),\n });\n}\n\n/** Bind the user-supplied emitter, return a curried emit function. */\nexport function createEmitter(onMetric?: MetricEmitter): MetricEmitter {\n return (event: MetricEvent) => {\n bump(event);\n if (onMetric) {\n try {\n onMetric(event);\n } catch {\n // Telemetry must never crash the cache layer.\n }\n }\n };\n}\n\n/** Snapshot of current counters. Useful for `/api/metrics` style endpoints. */\nexport function getMetricSnapshot(): Record<\n MetricEventType,\n { count: number; avgMs: number; lastTs: number } | undefined\n> {\n const out: Partial<\n Record<MetricEventType, { count: number; avgMs: number; lastTs: number }>\n > = {};\n for (const [type, c] of counters.entries()) {\n out[type] = {\n count: c.count,\n avgMs: c.count > 0 ? c.totalMs / c.count : 0,\n lastTs: c.lastTs,\n };\n }\n return out as Record<\n MetricEventType,\n { count: number; avgMs: number; lastTs: number } | undefined\n >;\n}\n\n/** Reset counters. Test-only export; not part of the public API. */\nexport function __resetMetricsForTest(): void {\n counters.clear();\n}\n","/**\n * Build namespace resolution.\n *\n * Why this matters: the reference implementation's \"static chunk 404\" incident\n * was caused by old prerender HTML from a previous deployment hitting in Redis.\n * Two deployments shared the same cache key prefix, so a new build's request\n * could deserialize an entry that referenced static chunks deleted by the\n * deployment swap.\n *\n * Embedding a per-deployment namespace into every entry key fixes this:\n * next-incremental:entry:<commit-sha>:<path>\n *\n * Rolling forward to a new SHA invalidates everything atomically without\n * needing a manual flush. Tags remain shared across deployments so\n * `revalidateTag()` keeps cross-deployment semantics.\n */\n\nconst FALLBACK = \"unversioned\";\n\n/**\n * Resolve the namespace value. Pure helper used at runtime when constructing\n * keys.\n */\nexport function resolveBuildNamespace(\n override?: string | (() => string)\n): string {\n if (override !== undefined) {\n return typeof override === \"function\" ? override() : override;\n }\n return (\n process.env.DEPLOYMENT_VERSION ??\n process.env.GIT_HASH ??\n process.env.NEXT_DEPLOYMENT_ID ??\n FALLBACK\n );\n}\n\n/**\n * Build a namespaced key. When `hashTag` is true, the namespace is wrapped in\n * `{}` so multi-key Lua scripts on Redis Cluster all hash to the same slot.\n *\n * Example:\n * buildKey(\"next-incremental:entry:\", \"ns42\", \"/blog/hello\", false)\n * → \"next-incremental:entry:ns42:/blog/hello\"\n * buildKey(\"next-cache:tag:\", \"ns42\", \"post-1\", true)\n * → \"next-cache:tag:{ns42}:post-1\"\n */\nexport function buildKey(\n prefix: string,\n namespace: string,\n rest: string,\n hashTag = false\n): string {\n const ns = hashTag ? `{${namespace}}` : namespace;\n return `${prefix}${ns}:${rest}`;\n}\n","/**\n * Detect whether Next.js is in the production build phase.\n *\n * During `next build` (or `next start --build`), Next pre-renders pages with\n * `'use cache'` directives, which means it calls `cacheHandlers.get` / `.set`\n * before any runtime infrastructure exists. Connecting to Redis in this phase\n * blows up the build with ECONNREFUSED.\n *\n * This is the same root cause that left `@fortedigital/nextjs-cache-handler`\n * PR #207 stalled for 3+ months — the maintainer's review explicitly demanded\n * `PHASE_PRODUCTION_BUILD` handling.\n *\n * The constant value comes from `next/constants`:\n * PHASE_PRODUCTION_BUILD = 'phase-production-build'\n *\n * We intentionally read process.env at call time (not import time) so tests\n * and apps that set NEXT_PHASE late still observe the change.\n */\nconst PHASE_PRODUCTION_BUILD = \"phase-production-build\";\n\nexport function isBuildPhase(): boolean {\n return process.env.NEXT_PHASE === PHASE_PRODUCTION_BUILD;\n}\n\n/**\n * Decide whether to attempt a Redis connection given the configured fallback\n * strategy. Used as the gate at the top of every handler method.\n *\n * Returns `false` ⇒ skip Redis entirely, route through the in-memory fallback\n * Returns `true` ⇒ proceed with the configured client\n */\nexport function shouldUseRedis(opts: {\n fallback?: \"auto\" | \"always\" | \"never\";\n isBuildPhase?: () => boolean;\n}): boolean {\n if (opts.fallback === \"always\") return false;\n const detector = opts.isBuildPhase ?? isBuildPhase;\n if (detector()) return false;\n return true;\n}\n","/**\n * ReadableStream <-> base64 conversion for the cacheHandlers value field.\n *\n * Per the Next 16 spec (docs/next16-spec.md §2.2):\n * value: ReadableStream<Uint8Array>\n *\n * Redis stores strings, so we materialize the stream into a Buffer, encode as\n * base64, persist as part of a JSON envelope, then reconstruct a single-chunk\n * ReadableStream on read.\n *\n * Spec-mandated behavior on partial writes:\n * \"the stream may error partway through rendering. Your handler should\n * decide whether to keep partial entries or discard them. Discarding is\n * safer.\"\n * → readStreamFully throws on stream errors. The caller must catch and skip\n * the SET operation when this throws.\n */\n\nexport async function readStreamFully(\n stream: ReadableStream<Uint8Array>\n): Promise<Buffer> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n try {\n \n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n return Buffer.concat(chunks.map((c) => Buffer.from(c)));\n}\n\nexport function bufferToStream(buf: Buffer): ReadableStream<Uint8Array> {\n // Capture once; the controller's enqueue copy isn't necessary because the\n // backing Buffer is owned by us at this point.\n return new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(new Uint8Array(buf));\n controller.close();\n },\n });\n}\n\nexport interface StoredEntryEnvelope {\n /** base64-encoded stream contents */\n value: string;\n tags: string[];\n stale: number;\n timestamp: number;\n expire: number;\n revalidate: number;\n}\n\nexport function encodeEnvelope(\n buf: Buffer,\n meta: Omit<StoredEntryEnvelope, \"value\">\n): string {\n const envelope: StoredEntryEnvelope = {\n value: buf.toString(\"base64\"),\n ...meta,\n };\n return JSON.stringify(envelope);\n}\n\nexport function decodeEnvelope(raw: string): StoredEntryEnvelope | null {\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (\n !parsed ||\n typeof parsed !== \"object\" ||\n typeof (parsed as StoredEntryEnvelope).value !== \"string\"\n ) {\n return null;\n }\n return parsed as StoredEntryEnvelope;\n } catch {\n return null;\n }\n}\n","/**\n * Stale-While-Revalidate decision logic for the cacheHandlers (plural)\n * interface.\n *\n * Next.js 16 distinguishes three time axes for an entry, all expressed as\n * seconds offset from `timestamp` (ms epoch):\n *\n * timestamp ───── revalidate ───── stale ───── expire ─────►\n * │ │ │ │\n * fresh SWR window SWR window hard\n * │ (background ends miss\n * │ refresh)\n *\n * The reference handler in next-redis-cache-demo collapsed this into a single\n * `revalidate` check, returning `undefined` (cache miss) the moment the entry\n * crossed `revalidate`. That defeats SWR — every user past the revalidate\n * boundary pays the full origin cost instead of getting an instant stale read.\n *\n * The corrected partition:\n * - age <= revalidate * 1000 → \"fresh\"\n * - revalidate*1000 < age <= expire*1000 → \"stale\" (still served, refresh\n * happens in background per Next.js' own scheduling)\n * - age > expire*1000 → \"expired\" (true miss, evict the entry)\n *\n * This module is pure logic. It does not touch Redis. The handler's `get`\n * threads the entry through `partitionEntry` and decides what to return.\n */\n\nimport type { CacheComponentsEntry } from \"../types.js\";\n\nexport type EntryFreshness = \"fresh\" | \"stale\" | \"expired\";\n\nexport interface PartitionResult {\n freshness: EntryFreshness;\n /** Age in ms since the entry's timestamp. */\n ageMs: number;\n}\n\nconst SECOND_MS = 1000;\n\n/**\n * Classify an entry into one of the three freshness buckets.\n *\n * Edge cases:\n * - Negative age (clock skew where timestamp is in the future): treat as fresh.\n * The entry was clearly just written; we don't punish the read for a 2s\n * clock drift between the writer and reader instances.\n * - expire === 0: per Next.js' \"no hard expire\" sentinel. We map it to a\n * practical upper bound (one year) so the partition still works. This\n * matches the TTL-fallback behavior of the reference handler.\n * - revalidate >= expire: degenerate config. We honor revalidate as the\n * fresh→stale boundary and clamp expire upward when it's smaller.\n */\nexport function partitionEntry(\n entry: Pick<CacheComponentsEntry, \"timestamp\" | \"revalidate\" | \"expire\">,\n now: number = Date.now()\n): PartitionResult {\n const ageMs = now - entry.timestamp;\n\n if (ageMs < 0) {\n return { freshness: \"fresh\", ageMs };\n }\n\n const revalidateMs = Math.max(0, entry.revalidate) * SECOND_MS;\n const rawExpireMs = entry.expire === 0 ? Number.POSITIVE_INFINITY : Math.max(0, entry.expire) * SECOND_MS;\n const expireMs = Math.max(rawExpireMs, revalidateMs);\n\n if (ageMs <= revalidateMs) {\n return { freshness: \"fresh\", ageMs };\n }\n if (ageMs <= expireMs) {\n return { freshness: \"stale\", ageMs };\n }\n return { freshness: \"expired\", ageMs };\n}\n\n/**\n * Decide whether to honor a `staleWhileRevalidate` config knob. When the user\n * disables SWR, \"stale\" entries are treated as expired (preserving v0\n * behavior).\n */\nexport function shouldServeStale(\n result: PartitionResult,\n staleWhileRevalidate: boolean\n): boolean {\n return result.freshness === \"fresh\" || (result.freshness === \"stale\" && staleWhileRevalidate);\n}\n","/**\n * `cacheHandler` (singular) entry point — for Pages Router ISR and on-demand\n * revalidation. See docs/next16-spec.md §3.\n *\n * Usage:\n *\n * // cache-incremental.config.ts\n * import { createIncrementalCacheHandler } from \"@leejpsd/nextjs-cache-handler/incremental\";\n * module.exports = createIncrementalCacheHandler({\n * client: { type: \"redis\", url: process.env.REDIS_URL! },\n * buildNamespace: process.env.DEPLOYMENT_VERSION,\n * });\n *\n * // next.config.ts\n * const nextConfig = {\n * cacheHandler: require.resolve(\"./cache-incremental.config.ts\"),\n * cacheMaxMemorySize: 0, // delegate entirely to this handler\n * };\n */\n\nexport {\n createIncrementalCacheHandler,\n IncrementalRedisCacheHandler,\n} from \"./handler.js\";\nexport type { IncrementalCtx } from \"./handler.js\";\n","/**\n * Spec-compliant `cacheHandler` (singular) implementation. See\n * docs/next16-spec.md §3.\n *\n * Used for:\n * - Pages Router ISR\n * - On-demand ISR (`res.revalidate`, `x-prerender-revalidate`)\n * - `fetch(..., { next: { tags } })` cache (kind: FETCH)\n * - App Router page/route HTML (when not using `'use cache'`)\n *\n * Differs from cache-components handler in two important ways:\n * 1. `value` is a plain Buffer/string, not a stream\n * 2. Tag invalidation is encoded as `{stale, expired}` payloads stored at\n * `next-incremental:tag:<tag>` (no namespace prefix — tags are shared\n * across deployments by design so revalidateTag survives a deploy)\n */\n\nimport { CacheTimeoutError, withAbortSignal } from \"../shared/abort.js\";\nimport { compressValue, decompressValue } from \"../shared/compress.js\";\nimport { ConnectionManager } from \"../shared/client/index.js\";\nimport { defaultLogger } from \"../shared/logger.js\";\nimport { MemoryStore } from \"../shared/memory-fallback.js\";\nimport { createEmitter } from \"../shared/metrics.js\";\nimport { buildKey, resolveBuildNamespace } from \"../shared/namespace.js\";\nimport { shouldUseRedis } from \"../shared/build-phase.js\";\nimport type {\n CacheHandlerOptions,\n IncrementalCacheData,\n Logger,\n MetricEmitter,\n} from \"../types.js\";\n\nimport {\n deserializeCacheRecord,\n serializeCacheRecord,\n} from \"./serialize.js\";\n\n// ─── Defaults ────────────────────────────────────────────────────────────────\n\nconst DEFAULT_KEY_PREFIX = \"next-incremental:\";\nconst ENTRY_SUFFIX = \"entry:\";\nconst TAG_SUFFIX = \"tag:\";\nconst INSTANCE_LOCAL_TAG_PREFIX = \"instance-local:\";\nconst ONE_YEAR_SEC = 60 * 60 * 24 * 365;\nconst MIN_TTL_SEC = 60;\nconst DEFAULT_ABORT_MS = 1500;\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface IncrementalCtx {\n kind?: string;\n /** Next 15 passes a lowercase kind hint (\"fetch\" | \"app\" | \"pages\"). */\n kindHint?: string;\n tags?: string[];\n softTags?: string[];\n revalidatedTags?: string[];\n /** Next 16 shape. */\n cacheControl?: { revalidate?: number | false };\n /** Next 15 shape — revalidate sits directly on the ctx. */\n revalidate?: number | false;\n fetchCache?: boolean;\n}\n\ninterface CacheRecord {\n lastModified: number;\n value: IncrementalCacheData[\"value\"];\n}\n\ninterface TagState {\n /** Last revalidate timestamp (ms). Soft — only fetch entries treat this as expired. */\n stale?: number;\n /** Hard expiration timestamp (ms). All entry kinds treat this as expired. */\n expired?: number;\n}\n\n// ─── State ───────────────────────────────────────────────────────────────────\n\ninterface HandlerState {\n opts: Required<\n Pick<\n CacheHandlerOptions,\n \"abortTimeoutMs\" | \"fallback\" | \"hashTag\" | \"keyPrefix\"\n >\n > & { rest: CacheHandlerOptions };\n logger: Logger;\n emit: MetricEmitter;\n conn: ConnectionManager;\n memEntries: MemoryStore<string>;\n /** Tag states, by bare tag (no namespace prefix — see tagMetaKey comment). */\n memTagStates: Map<string, TagState>;\n resolveNs: () => string;\n}\n\nfunction gateRedis(state: HandlerState): boolean {\n const fb = state.opts.fallback;\n const ibp = state.opts.rest.isBuildPhase;\n return ibp ? shouldUseRedis({ fallback: fb, isBuildPhase: ibp }) : shouldUseRedis({ fallback: fb });\n}\n\nfunction gateRedisInit(state: HandlerState): boolean {\n return gateRedis(state);\n}\n\nfunction init(opts: CacheHandlerOptions): HandlerState {\n const logger = opts.logger ?? defaultLogger;\n const emit = createEmitter(opts.onMetric);\n const conn = new ConnectionManager(opts.client, (err) => {\n logger.warn(\"Redis client error (incremental)\", { message: err.message });\n emit({ type: \"redis.connect.failed\", meta: { message: err.message } });\n });\n return {\n opts: {\n abortTimeoutMs: opts.abortTimeoutMs ?? DEFAULT_ABORT_MS,\n fallback: opts.fallback ?? \"auto\",\n hashTag: opts.hashTag ?? false,\n keyPrefix: opts.keyPrefix ?? DEFAULT_KEY_PREFIX,\n rest: opts,\n },\n logger,\n emit,\n conn,\n memEntries: new MemoryStore<string>(opts.memoryMaxEntries),\n memTagStates: new Map(),\n resolveNs: () => resolveBuildNamespace(opts.buildNamespace),\n };\n}\n\n// ─── Key helpers ─────────────────────────────────────────────────────────────\n\nfunction entryKey(state: HandlerState, cacheKey: string): string {\n // Entries ARE namespaced by build — the whole point of BUILD_NAMESPACE.\n return buildKey(\n `${state.opts.keyPrefix}${ENTRY_SUFFIX}`,\n state.resolveNs(),\n cacheKey,\n state.opts.hashTag\n );\n}\n\nfunction tagMetaKey(state: HandlerState, tag: string): string {\n // Tag states are intentionally NOT namespaced. revalidateTag should be\n // observable from new deployments too (otherwise a deploy-time invalidation\n // is lost). See incremental-cache-handler.js comment in reference impl.\n return `${state.opts.keyPrefix}${TAG_SUFFIX}${tag}`;\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction normalizeTags(tags: unknown): string[] {\n return Array.isArray(tags)\n ? tags.filter((t): t is string => typeof t === \"string\" && t.length > 0)\n : [];\n}\n\nfunction shouldUseLocalIncrementalStore(tags: string[]): boolean {\n return tags.some((t) => t.startsWith(INSTANCE_LOCAL_TAG_PREFIX));\n}\n\nfunction extractTagsFromValue(\n value: IncrementalCacheData[\"value\"],\n ctx: IncrementalCtx | undefined\n): string[] {\n if (!value || typeof value !== \"object\") return [];\n const v = value as { kind?: string; tags?: unknown; headers?: Record<string, unknown> };\n\n if (v.kind === \"FETCH\") {\n return normalizeTags([\n ...normalizeTags(v.tags),\n ...normalizeTags(ctx?.tags),\n ...normalizeTags(ctx?.softTags),\n ]);\n }\n\n const headers = v.headers;\n if (!headers) return [];\n const tagsHeader = headers[\"x-next-cache-tags\"];\n if (typeof tagsHeader === \"string\") {\n return tagsHeader\n .split(\",\")\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n }\n if (Array.isArray(tagsHeader)) {\n return tagsHeader\n .flatMap((part) => String(part).split(\",\"))\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n }\n return [];\n}\n\nfunction isTagStateExpired(\n state: TagState | null,\n lastModified: number | undefined,\n isFetch: boolean\n): boolean {\n if (!state || typeof lastModified !== \"number\") return false;\n if (typeof state.expired === \"number\" && state.expired >= lastModified) return true;\n if (isFetch && typeof state.stale === \"number\" && state.stale >= lastModified) return true;\n return false;\n}\n\nfunction normalizeTtlSeconds(\n data: IncrementalCacheData[\"value\"],\n ctx: IncrementalCtx | undefined\n): number {\n if (data && typeof data === \"object\") {\n const d = data as { kind?: string; revalidate?: number | false };\n if (d.kind === \"FETCH\") {\n if (typeof d.revalidate === \"number\" && d.revalidate > 0) {\n return Math.min(Math.max(Math.ceil(d.revalidate), MIN_TTL_SEC), ONE_YEAR_SEC);\n }\n return ONE_YEAR_SEC;\n }\n }\n // Next 16 nests revalidate under cacheControl; Next 15 passes it directly.\n const revalidate = ctx?.cacheControl?.revalidate ?? ctx?.revalidate;\n if (revalidate === false || revalidate === undefined) return ONE_YEAR_SEC;\n if (typeof revalidate === \"number\" && revalidate > 0) {\n return Math.min(Math.max(Math.ceil(revalidate), MIN_TTL_SEC), ONE_YEAR_SEC);\n }\n return MIN_TTL_SEC;\n}\n\nasync function readTagStates(\n state: HandlerState,\n tags: string[]\n): Promise<(TagState | null)[]> {\n if (tags.length === 0) return [];\n\n const useRedis = gateRedisInit(state);\n if (!useRedis) {\n return tags.map((t) => state.memTagStates.get(t) ?? null);\n }\n\n try {\n return await withAbortSignal(\n \"incremental.readTagStates\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return tags.map((t) => state.memTagStates.get(t) ?? null);\n const values = await client.mGet(tags.map((t) => tagMetaKey(state, t)));\n return values.map((v) => {\n if (!v) return null;\n try {\n return JSON.parse(v) as TagState;\n } catch {\n return null;\n }\n });\n }\n );\n } catch {\n return tags.map((t) => state.memTagStates.get(t) ?? null);\n }\n}\n\n// ─── Handler class ──────────────────────────────────────────────────────────\n\nexport class IncrementalRedisCacheHandler {\n private readonly state: HandlerState;\n private readonly revalidatedTags: string[];\n /**\n * Request-scoped memo of Redis entry reads. Next.js instantiates this class\n * per request (and calls resetRequestCache() at request boundaries when it\n * reuses an instance), so entries live at most one request. Bounded by the\n * number of distinct cache keys a single request touches.\n */\n private readonly requestMemo = new Map<string, Promise<string | null>>();\n\n constructor(state: HandlerState, ctx?: { revalidatedTags?: string[] }) {\n this.state = state;\n this.revalidatedTags = normalizeTags(ctx?.revalidatedTags);\n }\n\n /**\n * Redis entry read, deduplicated per request: parallel RSC renders or\n * repeated fetch() calls hitting the same cache key share one GET. The\n * memoized promise never rejects — errors are converted to a miss (with\n * the same timeout metric the inline path emitted before).\n */\n private readEntryDeduped(eKey: string): Promise<string | null> {\n const memoized = this.requestMemo.get(eKey);\n if (memoized) {\n this.state.emit({ type: \"cache.get.deduped\" });\n return memoized;\n }\n const read = withAbortSignal(\n \"incremental.get\",\n this.state.opts.abortTimeoutMs,\n async () => {\n const client = await this.state.conn.getOrConnect();\n if (!client) return null;\n // Decompress inside the memoized promise so deduped callers don't\n // repeat the CPU work. Corrupt data rejects → miss via the catch.\n return await decompressValue(await client.get(eKey));\n }\n ).catch((err: unknown) => {\n if (err instanceof CacheTimeoutError) {\n this.state.emit({\n type: \"redis.timeout\",\n meta: { op: \"incremental.get\" },\n });\n }\n return null;\n });\n this.requestMemo.set(eKey, read);\n return read;\n }\n\n async get(\n cacheKey: string,\n ctx?: IncrementalCtx\n ): Promise<(CacheRecord & { tags?: string[] }) | null> {\n try {\n const requestedTags = normalizeTags([\n ...(ctx?.tags ?? []),\n ...(ctx?.softTags ?? []),\n ]);\n const useLocal = shouldUseLocalIncrementalStore(requestedTags);\n const eKey = entryKey(this.state, cacheKey);\n\n const useRedis =\n !useLocal &&\n gateRedis(this.state);\n\n let raw: string | null = null;\n if (useRedis) {\n raw = await this.readEntryDeduped(eKey);\n }\n // Memory is a fallback (or the primary store for instance-local tags);\n // `fallback: \"never\"` surfaces Redis unavailability as a miss instead.\n if (raw === null && (useLocal || this.state.opts.fallback !== \"never\")) {\n raw = this.state.memEntries.get(eKey);\n }\n if (raw === null) {\n this.state.emit({ type: \"cache.miss\" });\n return null;\n }\n\n const parsed = deserializeCacheRecord<CacheRecord>(raw);\n if (!parsed || typeof parsed !== \"object\" || !parsed.value) return null;\n\n const tags = extractTagsFromValue(parsed.value, ctx);\n if (tags.some((t) => this.revalidatedTags.includes(t))) {\n this.state.emit({ type: \"cache.miss\", meta: { reason: \"revalidated-this-request\" } });\n return null;\n }\n\n const tagStates = await readTagStates(this.state, tags);\n // Next 16 sends kind: \"FETCH\"; Next 15 sends kindHint: \"fetch\". The\n // stored value's own kind covers entries read without a hint.\n const isFetch =\n ctx?.kind === \"FETCH\" ||\n ctx?.kindHint?.toLowerCase() === \"fetch\" ||\n (typeof parsed.value === \"object\" &&\n parsed.value !== null &&\n (parsed.value as { kind?: string }).kind === \"FETCH\");\n if (tagStates.some((s) => isTagStateExpired(s, parsed.lastModified, isFetch))) {\n this.state.emit({ type: \"cache.miss\", meta: { reason: \"tag-state-expired\" } });\n return null;\n }\n\n this.state.emit({ type: \"cache.hit\" });\n return { ...parsed, tags };\n } catch (err) {\n this.state.logger.error(\"get() unexpected error\", {\n message: (err as Error).message,\n });\n return null;\n }\n }\n\n async set(\n cacheKey: string,\n data: IncrementalCacheData[\"value\"],\n ctx?: IncrementalCtx\n ): Promise<void> {\n if (!data) return;\n try {\n const tags = extractTagsFromValue(data, ctx);\n const useLocal = shouldUseLocalIncrementalStore(tags);\n const ttl = normalizeTtlSeconds(data, ctx);\n const record: CacheRecord = { lastModified: Date.now(), value: data };\n const serialized = serializeCacheRecord(record);\n const eKey = entryKey(this.state, cacheKey);\n // The stored value changes — a memoized read (including a memoized\n // miss) must not shadow it for the rest of the request.\n this.requestMemo.delete(eKey);\n\n const useRedis =\n !useLocal &&\n gateRedis(this.state);\n\n if (useRedis) {\n try {\n await withAbortSignal(\n \"incremental.set\",\n this.state.opts.abortTimeoutMs,\n async () => {\n const client = await this.state.conn.getOrConnect();\n if (!client) {\n if (this.state.opts.fallback !== \"never\") {\n this.state.memEntries.set(eKey, serialized, ttl);\n }\n return;\n }\n // Compress only the Redis-bound copy; memory stays plain.\n await client.set(\n eKey,\n await compressValue(\n serialized,\n this.state.opts.rest.compression\n ),\n { EX: ttl }\n );\n }\n );\n this.state.emit({ type: \"cache.set\", meta: { backend: \"redis\" } });\n return;\n } catch (err) {\n if (err instanceof CacheTimeoutError) {\n this.state.emit({ type: \"redis.timeout\", meta: { op: \"incremental.set\" } });\n }\n // Fall through to memory.\n }\n }\n\n if (useLocal || this.state.opts.fallback !== \"never\") {\n this.state.memEntries.set(eKey, serialized, ttl);\n this.state.emit({ type: \"cache.set\", meta: { backend: \"memory\" } });\n } else {\n this.state.emit({\n type: \"cache.set.failed\",\n meta: { reason: \"no-fallback\" },\n });\n }\n } catch (err) {\n this.state.logger.error(\"set() error\", {\n message: (err as Error).message,\n });\n this.state.emit({ type: \"cache.set.failed\" });\n }\n }\n\n async revalidateTag(\n tags: string | string[],\n durations?: { expire?: number }\n ): Promise<void> {\n const list = normalizeTags([tags].flat());\n if (list.length === 0) return;\n\n const useLocal = shouldUseLocalIncrementalStore(list);\n const useRedis = !useLocal && gateRedis(this.state);\n\n const now = Date.now();\n const payload: TagState = durations\n ? {\n stale: now,\n ...(durations.expire !== undefined\n ? { expired: now + durations.expire * 1000 }\n : {}),\n }\n : { expired: now };\n\n // Local first.\n for (const t of list) this.state.memTagStates.set(t, payload);\n\n if (!useRedis) {\n this.state.emit({\n type: payload.expired ? \"tag.invalidate.hard\" : \"tag.invalidate.soft\",\n meta: { count: list.length, backend: \"memory\" },\n });\n return;\n }\n\n try {\n await withAbortSignal(\n \"incremental.revalidateTag\",\n this.state.opts.abortTimeoutMs,\n async () => {\n const client = await this.state.conn.getOrConnect();\n if (!client) return;\n await Promise.all(\n list.map((t) =>\n client.set(tagMetaKey(this.state, t), JSON.stringify(payload), {\n EX: ONE_YEAR_SEC,\n })\n )\n );\n }\n );\n this.state.emit({\n type: payload.expired ? \"tag.invalidate.hard\" : \"tag.invalidate.soft\",\n meta: { count: list.length, backend: \"redis\" },\n });\n } catch (err) {\n this.state.logger.warn(\"revalidateTag() failed\", {\n message: (err as Error).message,\n });\n // Hard expirations should propagate so callers know to retry.\n if (payload.expired !== undefined) throw err;\n }\n }\n\n resetRequestCache(): void {\n this.requestMemo.clear();\n }\n}\n\n/**\n * Factory returning a class compatible with Next.js's `cacheHandler` (singular)\n * option. Next.js does `new CacheHandler(ctx)` at request time, so we close\n * over the configured state and produce a class with the spec-required\n * methods. Note: Next constructs the class with just `(ctx)`, so the returned\n * class's constructor signature accepts the single-arg shape.\n */\nexport interface NextCacheHandlerCtor {\n new (ctx?: { revalidatedTags?: string[] }): IncrementalRedisCacheHandler;\n}\n\nexport function createIncrementalCacheHandler(\n opts: CacheHandlerOptions\n): NextCacheHandlerCtor {\n const state = init(opts);\n\n class BoundIncrementalCacheHandler extends IncrementalRedisCacheHandler {\n constructor(ctx?: { revalidatedTags?: string[] }) {\n super(state, ctx);\n }\n }\n\n return BoundIncrementalCacheHandler;\n}\n","/**\n * JSON serialization with Buffer / Map support for ISR cache records.\n *\n * Next.js's IncrementalCacheValue can contain Buffer (rendered HTML body) and\n * Map instances (RSC payload metadata). Plain JSON.stringify destroys both.\n *\n * The `__type` discriminator approach is borrowed from the reference handler\n * in next-redis-cache-demo. The reviver also accepts the legacy\n * `{ type: \"Buffer\", data: number[] }` shape that Node.js's default\n * Buffer.toJSON produces.\n */\n\ninterface BufferEnvelope {\n __type: \"Buffer\";\n data: string;\n}\ninterface MapEnvelope {\n __type: \"Map\";\n entries: Array<[unknown, unknown]>;\n}\ntype Envelope = BufferEnvelope | MapEnvelope;\n\nfunction isEnvelope(value: unknown): value is Envelope {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"__type\" in value &&\n typeof (value as { __type: unknown }).__type === \"string\"\n );\n}\n\ninterface LegacyBufferShape {\n type: \"Buffer\";\n data: number[];\n}\n\nfunction isLegacyBufferShape(value: unknown): value is LegacyBufferShape {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { type?: unknown }).type === \"Buffer\" &&\n Array.isArray((value as { data?: unknown }).data)\n );\n}\n\nfunction replacer(_key: string, value: unknown): unknown {\n if (Buffer.isBuffer(value)) {\n const env: BufferEnvelope = {\n __type: \"Buffer\",\n data: value.toString(\"base64\"),\n };\n return env;\n }\n if (value instanceof Map) {\n const env: MapEnvelope = {\n __type: \"Map\",\n entries: Array.from(value.entries()) as Array<[unknown, unknown]>,\n };\n return env;\n }\n return value;\n}\n\nfunction reviver(_key: string, value: unknown): unknown {\n if (isLegacyBufferShape(value)) {\n return Buffer.from(value.data);\n }\n if (!isEnvelope(value)) return value;\n if (value.__type === \"Buffer\") {\n return Buffer.from((value as BufferEnvelope).data, \"base64\");\n }\n if (value.__type === \"Map\") {\n return new Map((value as MapEnvelope).entries);\n }\n return value;\n}\n\nexport function serializeCacheRecord(record: unknown): string {\n return JSON.stringify(record, replacer);\n}\n\nexport function deserializeCacheRecord<T = unknown>(serialized: string): T | null {\n try {\n return JSON.parse(serialized, reviver) as T;\n } catch {\n return null;\n }\n}\n"]}
1
+ {"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/shared/node-require.ts","../src/shared/client/adapter-redis.ts","../src/shared/client/adapter-ioredis.ts","../src/index.ts","../src/cache-components/index.ts","../src/cache-components/handler.ts","../src/shared/abort.ts","../src/shared/compress.ts","../src/shared/client/index.ts","../src/shared/logger.ts","../src/shared/lua/index.ts","../src/shared/lua/set-with-tags.lua","../src/shared/lua/revalidate-hard.lua","../src/shared/lua/refresh-tag-lock.lua","../src/shared/memory-fallback.ts","../src/shared/metrics.ts","../src/shared/namespace.ts","../src/shared/build-phase.ts","../src/cache-components/serialize.ts","../src/cache-components/swr.ts","../src/incremental/index.ts","../src/incremental/handler.ts","../src/incremental/serialize.ts"],"names":["path","adaptRedisV5","createRedisV5Client","adaptIoredis","createIoredisClient","adaptCluster","createIoredisCluster","createIoredisSentinel","DEFAULT_KEY_PREFIX","ENTRY_SUFFIX","TAG_SUFFIX","ONE_YEAR_SEC","DEFAULT_ABORT_MS","gateRedis","init","entryKey"],"mappings":"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","file":"index.js","sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","/**\n * A require() that works from BOTH build outputs.\n *\n * The client/OTel factories load optional peers (`redis`, `ioredis`,\n * `@opentelemetry/api`) lazily at runtime. A bare `require()` compiles fine\n * for CJS but becomes esbuild's `__require` fallback in the ESM build, which\n * throws \"Dynamic require of X is not supported\" in pure-ESM consumers.\n * `createRequire(import.meta.url)` is real in ESM, and tsup's `shims: true`\n * provides an `import.meta.url` polyfill for the CJS build.\n */\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\n\nconst packageRequire = createRequire(import.meta.url);\nconst cwdRequire = createRequire(\n path.join(process.cwd(), \"__resolve-anchor__.js\")\n);\n\nexport function nodeRequire(id: string): unknown {\n try {\n return packageRequire(id);\n } catch {\n // Symlinked installs (npm i <local-path>, pnpm's virtual store) resolve\n // import.meta.url to the package's REAL location, outside the app tree —\n // so peers installed by the app aren't reachable from that anchor. Retry\n // from the process CWD, which under a Next.js server is the app root.\n return cwdRequire(id);\n }\n}\n","/**\n * Adapter for `redis@5` (the official `node-redis` client).\n *\n * v5 already uses camelCase methods that match `RedisClientLike` almost\n * exactly, so this adapter is mostly a type assertion plus the\n * `createRedisV5Client` factory that codifies the \"1.5s connectTimeout,\n * reconnectStrategy: false\" defaults validated in production by the reference\n * implementation.\n */\n\nimport type { RedisClientType } from \"redis\";\n\nimport type { RedisClientConfig, RedisClientLike } from \"../../types.js\";\nimport { nodeRequire } from \"../node-require.js\";\n\nexport function adaptRedisV5(client: RedisClientType): RedisClientLike {\n return client as unknown as RedisClientLike;\n}\n\nexport function createRedisV5Client(\n config: Extract<RedisClientConfig, { type: \"redis\" }>\n): RedisClientType {\n // Lazy require so consumers using ioredis only don't pay the cost.\n // We do `require` instead of `await import` here because the parent\n // `buildClient` is already in an async context that handles awaiting.\n \n const { createClient } = nodeRequire(\"redis\") as typeof import(\"redis\");\n const useTls = config.tls ?? config.url.startsWith(\"rediss://\");\n\n // redis@5 has a discriminated socket union (TCP / TLS / IPC) and disallows\n // explicit `undefined` under exactOptionalPropertyTypes. Build the options\n // object incrementally so optional fields stay absent when not set.\n \n const opts: any = {\n url: config.url,\n socket: {\n connectTimeout: config.connectTimeout ?? 1500,\n reconnectStrategy: false,\n ...(useTls ? { tls: true } : {}),\n },\n };\n if (config.password !== undefined) opts.password = config.password;\n\n return createClient(opts) as RedisClientType;\n}\n","/**\n * Adapter for `ioredis` (and `ioredis.Cluster`).\n *\n * ioredis uses snake_case method names (`sadd`, `smembers`, `mget`) and a\n * stream-based scan. We normalize both into the camelCase / async-iterable\n * `RedisClientLike` contract so the handlers don't need to know which client\n * is underneath.\n */\n\nimport type { Cluster, Redis } from \"ioredis\";\n\nimport type { RedisClientConfig, RedisClientLike } from \"../../types.js\";\nimport { nodeRequire } from \"../node-require.js\";\n\ntype AnyRedis = Redis | Cluster;\n\nfunction adapt(client: AnyRedis, isClusterClient = false): RedisClientLike {\n return {\n get isOpen() {\n // ioredis exposes a `status` string. Both single-node and cluster\n // report \"ready\" once connected.\n return client.status === \"ready\";\n },\n connect: async () => {\n if (client.status !== \"ready\" && client.status !== \"connecting\") {\n await client.connect();\n }\n },\n get: (k) => client.get(k),\n set: (k, v, opts) =>\n opts?.EX !== undefined\n ? client.set(k, v, \"EX\", opts.EX)\n : client.set(k, v),\n del: async (keys) => {\n const arr = Array.isArray(keys) ? keys : [keys];\n if (arr.length === 0) return 0;\n return client.del(...arr);\n },\n sAdd: async (k, m) => {\n const arr = Array.isArray(m) ? m : [m];\n if (arr.length === 0) return 0;\n return client.sadd(k, ...arr);\n },\n sMembers: (k) => client.smembers(k),\n expire: async (k, s) => {\n const r = await client.expire(k, s);\n return r;\n },\n mGet: async (keys) => {\n if (keys.length === 0) return [];\n return client.mget(...keys);\n },\n eval: (script, opts) =>\n client.eval(\n script,\n opts.keys.length,\n ...opts.keys,\n ...opts.arguments\n ) as Promise<unknown>,\n evalSha: (sha, opts) =>\n client.evalsha(\n sha,\n opts.keys.length,\n ...opts.keys,\n ...opts.arguments\n ) as Promise<unknown>,\n scriptLoad: async (script) =>\n (await client.script(\"LOAD\", script)) as string,\n scanIterator: async function* ({ MATCH, COUNT }) {\n // Cluster does not support a single SCAN cursor across slots; use\n // ioredis's per-node iterator there. Single-node: standard SCAN cursor.\n if (isClusterClient) {\n const cluster = client as Cluster;\n for (const node of cluster.nodes(\"master\")) {\n let cursor = \"0\";\n do {\n const [next, batch]: [string, string[]] = await node.scan(\n cursor,\n \"MATCH\",\n MATCH,\n \"COUNT\",\n COUNT ?? 100\n );\n cursor = next;\n if (batch.length > 0) yield batch;\n } while (cursor !== \"0\");\n }\n } else {\n const redis = client as Redis;\n let cursor = \"0\";\n do {\n const [next, batch]: [string, string[]] = await redis.scan(\n cursor,\n \"MATCH\",\n MATCH,\n \"COUNT\",\n COUNT ?? 100\n );\n cursor = next;\n if (batch.length > 0) yield batch;\n } while (cursor !== \"0\");\n }\n },\n ping: () => client.ping(),\n on: (event, listener) => {\n client.on(event, listener);\n return client;\n },\n dispose: () => {\n client.disconnect();\n },\n };\n}\n\nexport function adaptIoredis(client: Redis): RedisClientLike {\n return adapt(client, false);\n}\n\nexport function adaptCluster(cluster: Cluster): RedisClientLike {\n return adapt(cluster, true);\n}\n\nexport function createIoredisClient(\n config: Extract<RedisClientConfig, { type: \"ioredis\" }>\n): Redis {\n \n const IORedis = nodeRequire(\"ioredis\") as typeof import(\"ioredis\");\n // ioredis exports the class as both `default` and a named property.\n // Hitting the default works for both ESM and CJS consumers.\n const Ctor = IORedis.default ?? (IORedis as unknown as typeof import(\"ioredis\").default);\n return new Ctor(config.url, {\n password: config.password,\n connectTimeout: config.connectTimeout ?? 1500,\n tls: config.tls ? {} : undefined,\n lazyConnect: true,\n maxRetriesPerRequest: 1,\n // Batch same-tick commands into one RTT (matches redis@5's default\n // behavior) — makes Promise.all fan-outs a single pipeline.\n enableAutoPipelining: true,\n });\n}\n\nexport function createIoredisSentinel(\n config: Extract<RedisClientConfig, { type: \"sentinel\" }>\n): Redis {\n const IORedis = nodeRequire(\"ioredis\") as typeof import(\"ioredis\");\n const Ctor = IORedis.default ?? (IORedis as unknown as typeof import(\"ioredis\").default);\n return new Ctor({\n sentinels: config.sentinels,\n name: config.name,\n password: config.password,\n sentinelPassword: config.sentinelPassword,\n connectTimeout: config.connectTimeout ?? 1500,\n tls: config.tls ? {} : undefined,\n lazyConnect: true,\n maxRetriesPerRequest: 1,\n enableAutoPipelining: true,\n });\n}\n\nexport function createIoredisCluster(\n config: Extract<RedisClientConfig, { type: \"cluster\" }>\n): Cluster {\n \n const IORedis = nodeRequire(\"ioredis\") as typeof import(\"ioredis\");\n const ClusterCtor =\n IORedis.Cluster ??\n (IORedis.default as unknown as { Cluster: typeof import(\"ioredis\").Cluster })\n .Cluster;\n return new ClusterCtor(config.nodes, {\n redisOptions: {\n password: config.password,\n tls: config.tls ? {} : undefined,\n },\n enableReadyCheck: true,\n lazyConnect: true,\n // Same-slot commands issued in the same tick share one pipeline.\n enableAutoPipelining: true,\n });\n}\n","/**\n * @leejpsd/nextjs-cache-handler — main barrel.\n *\n * Most consumers should import from the dedicated subpath that matches the\n * Next.js option they're configuring:\n *\n * import { createCacheComponentsHandler } from \"@leejpsd/nextjs-cache-handler/cache-components\";\n * import { createIncrementalCacheHandler } from \"@leejpsd/nextjs-cache-handler/incremental\";\n *\n * The root barrel exists so a single `import { ... } from \"@leejpsd/nextjs-cache-handler\"`\n * works for code that wires up both handlers.\n */\n\nexport {\n createCacheComponentsHandler,\n type CacheComponentsHandler,\n partitionEntry,\n shouldServeStale,\n} from \"./cache-components/index.js\";\n\nexport {\n createIncrementalCacheHandler,\n IncrementalRedisCacheHandler,\n type IncrementalCtx,\n} from \"./incremental/index.js\";\n\nexport { CacheTimeoutError } from \"./shared/abort.js\";\nexport { isBuildPhase, shouldUseRedis } from \"./shared/build-phase.js\";\nexport { resolveBuildNamespace } from \"./shared/namespace.js\";\nexport { getMetricSnapshot } from \"./shared/metrics.js\";\n\nexport type {\n CacheHandlerOptions,\n CacheComponentsEntry,\n IncrementalCacheData,\n RedisClientLike,\n RedisClientConfig,\n RedisClientFactory,\n FallbackStrategy,\n MetricEvent,\n MetricEventType,\n MetricEmitter,\n Logger,\n} from \"./types.js\";\n","/**\n * `cacheHandlers` (plural) entry point — for the `'use cache'` directive.\n *\n * Use this from a wrapper module referenced by `next.config.ts`:\n *\n * // cache.config.ts\n * import { createCacheComponentsHandler } from \"@leejpsd/nextjs-cache-handler/cache-components\";\n * module.exports = createCacheComponentsHandler({\n * client: { type: \"redis\", url: process.env.REDIS_URL! },\n * buildNamespace: process.env.DEPLOYMENT_VERSION,\n * });\n *\n * // next.config.ts\n * const nextConfig = {\n * cacheComponents: true,\n * cacheHandlers: {\n * default: require.resolve(\"./cache.config.ts\"),\n * },\n * };\n */\n\nexport {\n createCacheComponentsHandler,\n type CacheComponentsHandler,\n} from \"./handler.js\";\nexport { partitionEntry, shouldServeStale } from \"./swr.js\";\n","/**\n * Spec-compliant `cacheHandlers` (plural) implementation. See docs/next16-spec.md.\n *\n * This module owns the five required methods (`get`, `set`, `refreshTags`,\n * `getExpiration`, `updateTags`) and threads them through:\n * - build-phase short-circuit (src/shared/build-phase.ts)\n * - per-call abort timeout (src/shared/abort.ts)\n * - in-memory fallback when Redis unavailable (src/shared/memory-fallback.ts)\n * - 3-axis SWR partition (./swr.ts)\n * - Lua-atomic SET-with-tags / hard-revalidate (src/shared/lua/)\n *\n * Error policy follows spec §6 verbatim — this module never re-throws on\n * `get` / `set`. `updateTags` with `expire === 0` (hard expire) propagates\n * so the user observes invalidation failures.\n */\n\nimport { CacheTimeoutError, withAbortSignal } from \"../shared/abort.js\";\nimport { compressValue, decompressValue } from \"../shared/compress.js\";\nimport { ConnectionManager } from \"../shared/client/index.js\";\nimport { defaultLogger } from \"../shared/logger.js\";\nimport { execLuaScript } from \"../shared/lua/index.js\";\nimport { MemoryStore, MemorySetStore } from \"../shared/memory-fallback.js\";\nimport { createEmitter } from \"../shared/metrics.js\";\nimport { buildKey, resolveBuildNamespace } from \"../shared/namespace.js\";\nimport { shouldUseRedis } from \"../shared/build-phase.js\";\nimport type {\n CacheComponentsEntry,\n CacheHandlerOptions,\n Logger,\n MetricEmitter,\n RedisClientLike,\n} from \"../types.js\";\n\nimport {\n bufferToStream,\n decodeEnvelope,\n encodeEnvelope,\n readStreamFully,\n} from \"./serialize.js\";\nimport { partitionEntry, shouldServeStale } from \"./swr.js\";\n\n// ─── Defaults / constants ────────────────────────────────────────────────────\n\nconst DEFAULT_KEY_PREFIX = \"next-cache:\";\nconst ENTRY_SUFFIX = \"entry:\";\nconst TAG_SUFFIX = \"tag:\";\nconst TAG_EXP_SUFFIX = \"tag-expiration:\";\nconst LOCK_SUFFIX = \"lock:\";\n\nconst DEFAULT_ABORT_MS = 1500;\nconst DEFAULT_LOCK_TTL_SEC = 10;\n/** When entry.expire === Infinity (the \"never\" sentinel), use this as the\n * Redis EX. One year matches the upstream cap and avoids leaking forever. */\nconst ONE_YEAR_SEC = 60 * 60 * 24 * 365;\n/** Fallback floor when both expire and revalidate are unset/0. */\nconst FALLBACK_TTL_SEC = 3600;\n/** TTL for tag-expiration markers — kept long so cross-deployment readers\n * can still observe an invalidation that happened in the previous deploy. */\nconst TAG_EXP_MARKER_TTL_SEC = 60 * 60 * 24 * 7; // 7 days\n\n// ─── Public factory contract ─────────────────────────────────────────────────\n\nexport interface CacheComponentsHandler {\n get(\n cacheKey: string,\n softTags: string[]\n ): Promise<CacheComponentsEntry | undefined>;\n set(\n cacheKey: string,\n pendingEntry: Promise<CacheComponentsEntry>\n ): Promise<void>;\n refreshTags(): Promise<void>;\n getExpiration(tags: string[]): Promise<number>;\n updateTags(\n tags: string[],\n durations?: { expire?: number }\n ): Promise<void>;\n}\n\n// ─── Implementation ──────────────────────────────────────────────────────────\n\ninterface HandlerState {\n opts: Required<\n Pick<\n CacheHandlerOptions,\n | \"abortTimeoutMs\"\n | \"fallback\"\n | \"staleWhileRevalidate\"\n | \"hashTag\"\n | \"keyPrefix\"\n | \"singleFlight\"\n | \"singleFlightLockTtlSec\"\n >\n > & { rest: CacheHandlerOptions };\n /** Stable instance identifier baked into refresh-lock owner field. Helps\n * operators tell from Redis which task held a given lock. */\n instanceId: string;\n logger: Logger;\n emit: MetricEmitter;\n conn: ConnectionManager;\n /** Memory cache for entries when Redis is unavailable. */\n memEntries: MemoryStore<string>;\n /** Memory tag-set index for memory fallback path. */\n memTags: MemorySetStore;\n /** Memory tag-expiration timestamps. Mirrors next-cache:tag-expiration:*. */\n memTagExp: Map<string, number>;\n /** Local mirror of recent tag invalidations refreshed from Redis. */\n localTagTimestamps: Map<string, number>;\n /** Resolved build namespace, computed once per call. */\n resolveNs: () => string;\n}\n\nfunction gateRedis(state: HandlerState): boolean {\n const fb = state.opts.fallback;\n const ibp = state.opts.rest.isBuildPhase;\n return ibp ? shouldUseRedis({ fallback: fb, isBuildPhase: ibp }) : shouldUseRedis({ fallback: fb });\n}\n\nfunction init(opts: CacheHandlerOptions): HandlerState {\n const logger = opts.logger ?? defaultLogger;\n const emit = createEmitter(opts.onMetric);\n const conn = new ConnectionManager(opts.client, (err) => {\n logger.warn(\"Redis client error\", { message: err.message });\n emit({ type: \"redis.connect.failed\", meta: { message: err.message } });\n });\n\n return {\n opts: {\n abortTimeoutMs: opts.abortTimeoutMs ?? DEFAULT_ABORT_MS,\n fallback: opts.fallback ?? \"auto\",\n staleWhileRevalidate: opts.staleWhileRevalidate ?? true,\n hashTag: opts.hashTag ?? false,\n keyPrefix: opts.keyPrefix ?? DEFAULT_KEY_PREFIX,\n singleFlight: opts.singleFlight ?? false,\n singleFlightLockTtlSec:\n opts.singleFlightLockTtlSec ?? DEFAULT_LOCK_TTL_SEC,\n rest: opts,\n },\n logger,\n emit,\n conn,\n memEntries: new MemoryStore<string>(opts.memoryMaxEntries),\n memTags: new MemorySetStore(opts.memoryMaxEntries),\n memTagExp: new Map(),\n localTagTimestamps: new Map(),\n resolveNs: () => resolveBuildNamespace(opts.buildNamespace),\n instanceId:\n process.env.HOSTNAME ||\n process.env.ECS_TASK_ID ||\n `pid-${process.pid}`,\n };\n}\n\n// ─── Key helpers ─────────────────────────────────────────────────────────────\n\nfunction entryKey(state: HandlerState, cacheKey: string): string {\n return buildKey(\n `${state.opts.keyPrefix}${ENTRY_SUFFIX}`,\n state.resolveNs(),\n cacheKey,\n state.opts.hashTag\n );\n}\n\nfunction tagKey(state: HandlerState, tag: string): string {\n return buildKey(\n `${state.opts.keyPrefix}${TAG_SUFFIX}`,\n state.resolveNs(),\n tag,\n state.opts.hashTag\n );\n}\n\nfunction tagExpKey(state: HandlerState, tag: string): string {\n return buildKey(\n `${state.opts.keyPrefix}${TAG_EXP_SUFFIX}`,\n state.resolveNs(),\n tag,\n state.opts.hashTag\n );\n}\n\nfunction lockKey(state: HandlerState, cacheKey: string): string {\n return buildKey(\n `${state.opts.keyPrefix}${LOCK_SUFFIX}`,\n state.resolveNs(),\n cacheKey,\n state.opts.hashTag\n );\n}\n\n/**\n * Try to acquire the single-flight lock for a stale cache key. Returns true\n * if this instance is the refresh leader, false if someone else already\n * holds the lock or Redis is unavailable.\n *\n * On any error path we return `false` (the safe default — we'd rather miss\n * the leadership signal than block the user response). The lock is purely\n * an observability + stampede-suppression hint; the entry itself is still\n * returned regardless of outcome.\n */\nasync function tryAcquireRefreshLock(\n state: HandlerState,\n cacheKey: string\n): Promise<boolean> {\n if (!state.opts.singleFlight) return false;\n if (!gateRedis(state)) return false;\n\n try {\n return await withAbortSignal(\n \"cacheHandlers.singleFlight.lock\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return false;\n const result = await execLuaScript<number>(\n client,\n \"refreshTagLock\",\n [lockKey(state, cacheKey)],\n [\n state.instanceId,\n String(state.opts.singleFlightLockTtlSec),\n ]\n );\n return result === 1;\n }\n );\n } catch {\n // Best-effort. A failed lock attempt should never block a serve.\n return false;\n }\n}\n\n// ─── TTL resolution ──────────────────────────────────────────────────────────\n\nfunction resolveTtlSeconds(entry: CacheComponentsEntry): number {\n // Per spec §4 cacheLife: expire can be Infinity; map to ONE_YEAR_SEC.\n if (Number.isFinite(entry.expire) && entry.expire > 0) {\n return Math.max(60, Math.ceil(entry.expire));\n }\n if (Number.isFinite(entry.revalidate) && entry.revalidate > 0) {\n return Math.max(60, Math.ceil(entry.revalidate));\n }\n if (entry.expire === Number.POSITIVE_INFINITY) {\n return ONE_YEAR_SEC;\n }\n return FALLBACK_TTL_SEC;\n}\n\n// ─── get() ───────────────────────────────────────────────────────────────────\n\nasync function getImpl(\n state: HandlerState,\n cacheKey: string,\n softTags: string[]\n): Promise<CacheComponentsEntry | undefined> {\n const start = Date.now();\n const useRedis = gateRedis(state);\n\n if (!useRedis && state.opts.fallback === \"never\") {\n state.emit({ type: \"cache.miss\", meta: { reason: \"no-redis\" } });\n return undefined;\n }\n\n const eKey = entryKey(state, cacheKey);\n\n // Try Redis first when allowed.\n let envelope: ReturnType<typeof decodeEnvelope> = null;\n let raw: string | null = null;\n\n if (useRedis) {\n try {\n raw = await withAbortSignal(\n \"cacheHandlers.get\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return null;\n return await client.get(eKey);\n }\n );\n } catch (err) {\n if (err instanceof CacheTimeoutError) {\n state.emit({ type: \"redis.timeout\", meta: { op: \"get\" } });\n } else {\n state.logger.warn(\"get() Redis error, falling back\", {\n message: (err as Error).message,\n });\n }\n raw = null;\n }\n }\n\n if (raw === null && state.opts.fallback !== \"never\") {\n raw = state.memEntries.get(eKey);\n if (raw !== null) state.emit({ type: \"fallback.activated\", meta: { op: \"get\" } });\n }\n\n if (raw === null) {\n state.emit({ type: \"cache.miss\", ms: Date.now() - start });\n return undefined;\n }\n\n try {\n raw = await decompressValue(raw);\n } catch {\n state.emit({ type: \"cache.miss\", meta: { reason: \"decode-error\" } });\n return undefined;\n }\n\n envelope = decodeEnvelope(raw as string);\n if (!envelope) {\n state.emit({ type: \"cache.miss\", meta: { reason: \"decode-error\" } });\n return undefined;\n }\n\n // 3-axis SWR partition.\n const partition = partitionEntry(envelope, Date.now());\n if (!shouldServeStale(partition, state.opts.staleWhileRevalidate)) {\n // Hard miss. Best-effort cleanup of the entry.\n if (useRedis) {\n try {\n await withAbortSignal(\n \"cacheHandlers.get.evict\",\n state.opts.abortTimeoutMs,\n async () => {\n const c = await state.conn.getOrConnect();\n if (c) await c.del(eKey);\n }\n );\n } catch {\n // Ignore — eviction is best-effort.\n }\n } else {\n state.memEntries.delete(eKey);\n }\n state.emit({\n type: \"cache.miss\",\n meta: { reason: \"expired\", freshness: partition.freshness },\n });\n return undefined;\n }\n\n // Tag freshness check. An entry is stale if ANY of its tags was invalidated\n // after entry.timestamp. Two tag sources must be considered:\n // 1. softTags — implicit route tags Next passes in (revalidatePath). Next\n // also enforces these itself via getExpiration(implicitTags), so this\n // handler-side check is defense in depth.\n // 2. envelope.tags — explicit tags carried on the entry via cacheTag().\n // Next does NOT consult the handler for these across requests (it only\n // checks the current action's pending/previous tags), so cross-request\n // soft invalidation — revalidateTag(tag, \"max\") — is entirely the\n // handler's job here. Checking only softTags made that a no-op (#1).\n const freshnessTags =\n softTags.length > 0 ? [...softTags, ...envelope.tags] : envelope.tags;\n let tagStale = false;\n if (freshnessTags.length > 0) {\n let mostRecent = 0;\n for (const t of freshnessTags) {\n const ts = state.localTagTimestamps.get(t);\n if (ts !== undefined && ts > mostRecent) mostRecent = ts;\n }\n if (mostRecent > envelope.timestamp) {\n // Soft invalidation is stale-while-revalidate per spec §2.3#updateTags\n // (\"entries can stay; subsequent reads treat them as stale\"): keep\n // serving the entry but classify it stale so it flows through the\n // background-refresh path below. Only when SWR is disabled (or the\n // entry is already hard-expired) do we degrade to a miss.\n if (state.opts.staleWhileRevalidate && partition.freshness !== \"expired\") {\n tagStale = true;\n } else {\n state.emit({ type: \"cache.miss\", meta: { reason: \"tag-invalidated\" } });\n return undefined;\n }\n }\n }\n\n const freshness = tagStale ? \"stale\" : partition.freshness;\n\n // For stale entries, try the single-flight refresh lock so only one\n // instance triggers the background refresh (when the option is on).\n // The lock outcome is purely informational — we always serve the entry.\n if (freshness === \"stale\") {\n const staleMeta = tagStale\n ? { freshness, reason: \"tag-invalidated\" }\n : { freshness };\n if (state.opts.singleFlight) {\n const isLeader = await tryAcquireRefreshLock(state, cacheKey);\n state.emit({\n type: isLeader\n ? \"cache.stale.refresh.leader\"\n : \"cache.stale.refresh.follower\",\n ms: Date.now() - start,\n meta: staleMeta,\n });\n } else {\n state.emit({\n type: \"cache.stale\",\n ms: Date.now() - start,\n meta: staleMeta,\n });\n }\n } else {\n state.emit({\n type: \"cache.hit\",\n ms: Date.now() - start,\n meta: { freshness },\n });\n }\n\n // When stale because of a tag invalidation (not time), present the entry as\n // just past its `revalidate` boundary so Next serves it immediately AND\n // schedules a background re-render (true SWR). Time-stale entries already\n // satisfy this through their real timestamp. The Math.min guard never makes\n // an entry look fresher than it actually is.\n const revalidateMs = Math.max(0, envelope.revalidate) * 1000;\n const outTimestamp = tagStale\n ? Math.min(envelope.timestamp, Date.now() - revalidateMs - 1)\n : envelope.timestamp;\n\n // Reconstruct stream and return.\n return {\n value: bufferToStream(Buffer.from(envelope.value, \"base64\")),\n tags: envelope.tags,\n stale: envelope.stale,\n timestamp: outTimestamp,\n expire: envelope.expire,\n revalidate: envelope.revalidate,\n };\n}\n\n// ─── set() ───────────────────────────────────────────────────────────────────\n\nasync function setImpl(\n state: HandlerState,\n cacheKey: string,\n pendingEntry: Promise<CacheComponentsEntry>\n): Promise<void> {\n // Spec mandates awaiting the promise before reading value.\n let entry: CacheComponentsEntry;\n try {\n entry = await pendingEntry;\n } catch (err) {\n state.logger.warn(\"pendingEntry rejected, skipping set()\", {\n message: (err as Error).message,\n });\n state.emit({ type: \"cache.set.failed\", meta: { reason: \"pending-rejected\" } });\n return;\n }\n\n let buf: Buffer;\n try {\n buf = await readStreamFully(entry.value);\n } catch (err) {\n // Partial writes — discard per spec §2.3#set.\n state.logger.warn(\"stream errored mid-read, discarding entry\", {\n message: (err as Error).message,\n });\n state.emit({ type: \"cache.set.failed\", meta: { reason: \"partial-stream\" } });\n return;\n }\n\n const eKey = entryKey(state, cacheKey);\n const ttl = resolveTtlSeconds(entry);\n const payload = encodeEnvelope(buf, {\n tags: entry.tags,\n stale: entry.stale,\n timestamp: entry.timestamp,\n expire: entry.expire,\n revalidate: entry.revalidate,\n });\n\n const useRedis = gateRedis(state);\n\n if (!useRedis) {\n state.emit({ type: \"build_phase.skip\", meta: { op: \"set\" } });\n if (state.opts.fallback !== \"never\") {\n state.memEntries.set(eKey, payload, ttl);\n for (const t of entry.tags) {\n state.memTags.sAdd(tagKey(state, t), eKey);\n state.memTags.expire(tagKey(state, t), ttl);\n }\n }\n state.emit({ type: \"cache.set\", meta: { backend: \"memory\" } });\n return;\n }\n\n try {\n await withAbortSignal(\n \"cacheHandlers.set\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) {\n if (state.opts.fallback !== \"never\") {\n state.memEntries.set(eKey, payload, ttl);\n }\n return;\n }\n // Compress only the Redis-bound copy — the memory fallback keeps the\n // plain payload (local reads shouldn't pay decompress CPU).\n const wirePayload = await compressValue(\n payload,\n state.opts.rest.compression\n );\n if (entry.tags.length === 0) {\n // No tags → simple SET.\n await client.set(eKey, wirePayload, { EX: ttl });\n } else {\n await luaSetWithTags(client, state, eKey, wirePayload, ttl, entry.tags);\n }\n }\n );\n state.emit({ type: \"cache.set\", meta: { backend: \"redis\" } });\n } catch (err) {\n if (err instanceof CacheTimeoutError) {\n state.emit({ type: \"redis.timeout\", meta: { op: \"set\" } });\n } else {\n state.logger.warn(\"set() failed (best-effort)\", {\n message: (err as Error).message,\n });\n }\n state.emit({ type: \"cache.set.failed\", meta: { reason: \"redis-error\" } });\n // No re-throw per spec error policy.\n }\n}\n\nasync function luaSetWithTags(\n client: RedisClientLike,\n state: HandlerState,\n eKey: string,\n payload: string,\n ttl: number,\n tags: string[]\n): Promise<void> {\n const tagKeys = tags.map((t) => tagKey(state, t));\n await execLuaScript<number>(\n client,\n \"setWithTags\",\n [eKey, ...tagKeys],\n [payload, String(ttl), String(ttl), String(tags.length)]\n );\n}\n\n// ─── refreshTags() ───────────────────────────────────────────────────────────\n\nasync function refreshTagsImpl(state: HandlerState): Promise<void> {\n // Per spec §6: errors here MUST be caught.\n if (\n !gateRedis(state)\n ) {\n return;\n }\n\n try {\n await withAbortSignal(\n \"cacheHandlers.refreshTags\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return;\n // Scan only the current namespace's markers. The old pattern omitted\n // the namespace, so every deploy's markers were scanned and then\n // discarded by stripExpPrefix; combined with a 500-key cap (SCAN\n // restarts at cursor 0 each call) markers past the cap were never\n // read. Chunk-by-chunk MGET replaces the cap: work per chunk stays\n // small and no marker is silently skipped.\n const ns = state.opts.hashTag\n ? `{${state.resolveNs()}}`\n : state.resolveNs();\n const pattern = `${escapeMatch(\n `${state.opts.keyPrefix}${TAG_EXP_SUFFIX}${ns}:`\n )}*`;\n const scanStartMs = Date.now();\n const fresh = new Map<string, number>();\n for await (const chunk of client.scanIterator({\n MATCH: pattern,\n COUNT: 100,\n })) {\n const keys = Array.isArray(chunk)\n ? chunk.map(String)\n : [String(chunk)];\n if (keys.length === 0) continue;\n const values = await client.mGet(keys);\n for (let i = 0; i < keys.length; i += 1) {\n const v = values[i];\n if (!v) continue;\n const ts = Number.parseInt(v, 10);\n if (!Number.isFinite(ts)) continue;\n // Strip prefix back to bare tag name.\n const key = keys[i];\n if (key === undefined) continue;\n const tag = stripExpPrefix(state, key);\n if (tag) fresh.set(tag, ts);\n }\n }\n // Invalidations recorded locally while the scan ran may not have had\n // visible markers yet — carry them over so they aren't lost.\n for (const [tag, ts] of state.localTagTimestamps) {\n if (ts >= scanStartMs && (fresh.get(tag) ?? 0) < ts) {\n fresh.set(tag, ts);\n }\n }\n // Wholesale replacement keeps the mirror bounded by live-marker\n // count: tags whose markers expired out of Redis (7d TTL) drop out\n // here. Only reached on a complete scan — a failed or timed-out scan\n // keeps the previous mirror instead of installing partial data.\n state.localTagTimestamps = fresh;\n }\n );\n } catch (err) {\n state.logger.warn(\"refreshTags() error swallowed\", {\n message: (err as Error).message,\n });\n }\n}\n\n/** Escape Redis MATCH glob metacharacters so key prefixes match literally. */\nfunction escapeMatch(s: string): string {\n return s.replace(/[\\\\*?[\\]]/g, \"\\\\$&\");\n}\n\n/** Cap for the process-local tag-timestamp mirrors. */\nconst MAX_LOCAL_TAG_ENTRIES = 10_000;\n\n/** Drop the oldest-timestamped entries until the map fits the cap. */\nfunction pruneOldestByTimestamp(\n map: Map<string, number>,\n maxEntries: number\n): void {\n if (map.size <= maxEntries) return;\n const byAge = [...map.entries()].sort((a, b) => a[1] - b[1]);\n const drop = map.size - maxEntries;\n for (let i = 0; i < drop; i += 1) {\n const entry = byAge[i];\n if (entry) map.delete(entry[0]);\n }\n}\n\nfunction stripExpPrefix(state: HandlerState, fullKey: string): string | null {\n const ns = state.resolveNs();\n const prefix = state.opts.hashTag\n ? `${state.opts.keyPrefix}${TAG_EXP_SUFFIX}{${ns}}:`\n : `${state.opts.keyPrefix}${TAG_EXP_SUFFIX}${ns}:`;\n return fullKey.startsWith(prefix) ? fullKey.slice(prefix.length) : null;\n}\n\n// ─── getExpiration() ────────────────────────────────────────────────────────\n\nasync function getExpirationImpl(\n state: HandlerState,\n tags: string[]\n): Promise<number> {\n if (tags.length === 0) return 0;\n\n let max = 0;\n for (const t of tags) {\n const local = state.localTagTimestamps.get(t);\n if (local !== undefined && local > max) max = local;\n const mem = state.memTagExp.get(t);\n if (mem !== undefined && mem > max) max = mem;\n }\n if (max > 0) {\n state.emit({ type: \"tag.expiration.read\", meta: { source: \"local\", count: tags.length } });\n return max;\n }\n\n // Cold path: no local hits → consult Redis if reachable.\n if (\n !gateRedis(state)\n ) {\n return 0;\n }\n\n try {\n return await withAbortSignal(\n \"cacheHandlers.getExpiration\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return 0;\n const keys = tags.map((t) => tagExpKey(state, t));\n const values = await client.mGet(keys);\n let m = 0;\n for (const v of values) {\n if (!v) continue;\n const n = Number.parseInt(v, 10);\n if (Number.isFinite(n) && n > m) m = n;\n }\n return m;\n }\n );\n } catch {\n // Best-effort. Falling back to 0 is safe (treats tags as never invalidated).\n return 0;\n }\n}\n\n// ─── updateTags() ───────────────────────────────────────────────────────────\n\nasync function updateTagsImpl(\n state: HandlerState,\n tags: string[],\n durations?: { expire?: number }\n): Promise<void> {\n if (tags.length === 0) return;\n const isHardExpire = durations?.expire === 0;\n const now = Date.now();\n\n // Local mirror update first — guarantees read-after-write within instance.\n for (const t of tags) {\n state.localTagTimestamps.set(t, now);\n state.memTagExp.set(t, now);\n }\n // memTagExp has no scan-based rebuild to shed dead tags (refreshTags only\n // replaces localTagTimestamps), so cap it here against unbounded growth in\n // high-tag-cardinality apps.\n pruneOldestByTimestamp(state.memTagExp, MAX_LOCAL_TAG_ENTRIES);\n\n if (\n !gateRedis(state)\n ) {\n if (isHardExpire) {\n // Drop matching entries from memory.\n for (const t of tags) {\n const tk = tagKey(state, t);\n const members = state.memTags.sMembers(tk);\n for (const m of members) state.memEntries.delete(m);\n state.memTags.delete(tk);\n }\n }\n state.emit({\n type: isHardExpire ? \"tag.invalidate.hard\" : \"tag.invalidate.soft\",\n meta: { count: tags.length, backend: \"memory\" },\n });\n return;\n }\n\n // Soft path: best-effort. Hard path: propagate failure.\n try {\n await withAbortSignal(\n \"cacheHandlers.updateTags\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) {\n if (isHardExpire) {\n throw new Error(\n \"[next-cache] hard updateTags requested but Redis unavailable\"\n );\n }\n return;\n }\n // Concurrent fan-out instead of a per-tag await chain: N tags cost\n // ~1 round trip (redis@5 auto-pipelines same-tick commands; ioredis\n // has enableAutoPipelining set in our factory) instead of N. With\n // many tags the sequential version could exceed abortTimeoutMs.\n await Promise.all(\n tags.map((t) =>\n isHardExpire\n ? execLuaScript<number>(\n client,\n \"revalidateHard\",\n [tagKey(state, t), tagExpKey(state, t)],\n [String(now), String(TAG_EXP_MARKER_TTL_SEC)]\n )\n : client.set(tagExpKey(state, t), String(now), {\n EX: TAG_EXP_MARKER_TTL_SEC,\n })\n )\n );\n }\n );\n state.emit({\n type: isHardExpire ? \"tag.invalidate.hard\" : \"tag.invalidate.soft\",\n meta: { count: tags.length, backend: \"redis\" },\n });\n } catch (err) {\n if (err instanceof CacheTimeoutError) {\n state.emit({ type: \"redis.timeout\", meta: { op: \"updateTags\" } });\n }\n if (isHardExpire) {\n // Hard failures must surface — read-your-own-writes was requested.\n throw err;\n }\n state.logger.warn(\"updateTags() soft path failed (best-effort)\", {\n message: (err as Error).message,\n });\n }\n}\n\n// ─── Public factory ─────────────────────────────────────────────────────────\n\nexport function createCacheComponentsHandler(\n opts: CacheHandlerOptions\n): CacheComponentsHandler {\n const state = init(opts);\n return {\n get: (cacheKey, softTags) => getImpl(state, cacheKey, softTags),\n set: (cacheKey, pendingEntry) => setImpl(state, cacheKey, pendingEntry),\n refreshTags: () => refreshTagsImpl(state),\n getExpiration: (tags) => getExpirationImpl(state, tags),\n updateTags: (tags, durations) => updateTagsImpl(state, tags, durations),\n };\n}\n","/**\n * Timeout-bounded operation wrapper. Surrounds every Redis call so a hung\n * connection doesn't lock up the Next.js request thread.\n *\n * Why explicit `withAbortSignal` instead of a Proxy (like @fortedigital's\n * `withAbortSignalProxy`):\n * - Stack traces stay clean; consumers see \"cacheHandlers.get\" not \"Proxy.apply\"\n * - Per-method timeouts can differ (set 500ms, updateTags 3000ms) without\n * re-instantiating a Proxy\n * - Easier to follow in `step into` debugging\n */\n\nexport class CacheTimeoutError extends Error {\n override readonly name = \"CacheTimeoutError\";\n constructor(\n public readonly opName: string,\n public readonly ms: number\n ) {\n super(`[@leejpsd/nextjs-cache-handler] ${opName} timed out after ${ms}ms`);\n }\n}\n\n/**\n * Run `fn` with a hard deadline. The provided AbortSignal is forwarded so the\n * inner operation can cancel cooperatively if it supports it.\n *\n * Behavior:\n * - If `fn` resolves before the deadline → resolved value is returned\n * - If the deadline fires first → CacheTimeoutError is thrown\n *\n * Note: aborting the AbortSignal does NOT close the underlying Redis socket.\n * The connection is retained for subsequent calls. We trust the Redis client\n * to recover on its own; we just stop waiting on this particular promise.\n */\nexport async function withAbortSignal<T>(\n opName: string,\n ms: number,\n fn: (signal: AbortSignal) => Promise<T>\n): Promise<T> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), ms);\n if (typeof timer === \"object\" && \"unref\" in timer) {\n // Don't keep the event loop alive just for this timer.\n (timer as { unref: () => void }).unref();\n }\n\n try {\n const timeoutPromise = new Promise<never>((_, reject) => {\n const onAbort = () => {\n ctrl.signal.removeEventListener(\"abort\", onAbort);\n reject(new CacheTimeoutError(opName, ms));\n };\n if (ctrl.signal.aborted) onAbort();\n else ctrl.signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n\n return await Promise.race([fn(ctrl.signal), timeoutPromise]);\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * Transparent value compression for Redis-bound entries (node:zlib — zero\n * added dependencies).\n *\n * Storage format: `<marker><base64>` with marker `__ncgz__:` (gzip) or\n * `__ncbr__:` (brotli). Values without a marker pass through untouched, so\n * mixed caches stay readable: entries written before compression was enabled,\n * or by instances configured differently, decode fine — decompression is\n * always active regardless of the local `compression` option.\n *\n * Base64 re-inflates the compressed bytes by ~33% (our client contract is\n * string-typed), but RSC/HTML payloads are text-heavy enough that the net\n * reduction is typically 3–5×. Payloads under 1 KiB are stored uncompressed —\n * at that size marker+header overhead can exceed the savings.\n *\n * Only entry values are compressed. Tag markers and tag states are a few\n * bytes each and stay plain.\n */\n\nimport { promisify } from \"node:util\";\nimport {\n brotliCompress,\n brotliDecompress,\n constants,\n gunzip,\n gzip,\n} from \"node:zlib\";\n\nconst gzipAsync = promisify(gzip);\nconst gunzipAsync = promisify(gunzip);\nconst brotliCompressAsync = promisify(brotliCompress);\nconst brotliDecompressAsync = promisify(brotliDecompress);\n\nexport type CompressionAlgo = \"gzip\" | \"brotli\";\n\nconst GZIP_MARKER = \"__ncgz__:\";\nconst BROTLI_MARKER = \"__ncbr__:\";\nconst MIN_COMPRESS_BYTES = 1024;\n\n/**\n * Brotli's default quality (11) is tuned for static assets and is far too\n * slow for a request-path cache write. 5 compresses close to gzip speed\n * while still beating it on ratio for text.\n */\nconst BROTLI_OPTS = {\n params: { [constants.BROTLI_PARAM_QUALITY]: 5 },\n};\n\nexport async function compressValue(\n value: string,\n algo: CompressionAlgo | undefined\n): Promise<string> {\n if (!algo || Buffer.byteLength(value) < MIN_COMPRESS_BYTES) return value;\n const input = Buffer.from(value);\n if (algo === \"gzip\") {\n return GZIP_MARKER + (await gzipAsync(input)).toString(\"base64\");\n }\n return (\n BROTLI_MARKER +\n (await brotliCompressAsync(input, BROTLI_OPTS)).toString(\"base64\")\n );\n}\n\n/**\n * Marker-dispatched decompression. Unmarked values are returned as-is.\n * Throws on corrupt compressed data — callers treat that as a cache miss.\n */\nexport async function decompressValue(\n value: string | null\n): Promise<string | null> {\n if (value === null) return null;\n if (value.startsWith(GZIP_MARKER)) {\n const buf = Buffer.from(value.slice(GZIP_MARKER.length), \"base64\");\n return (await gunzipAsync(buf)).toString(\"utf8\");\n }\n if (value.startsWith(BROTLI_MARKER)) {\n const buf = Buffer.from(value.slice(BROTLI_MARKER.length), \"base64\");\n return (await brotliDecompressAsync(buf)).toString(\"utf8\");\n }\n return value;\n}\n","/**\n * Client factory. Resolves a `RedisClientFactory | RedisClientConfig` to a\n * connected `RedisClientLike`, with idempotent connect.\n *\n * The factory caches the resolved client per-handler so repeated calls don't\n * spawn parallel connections. Adapter modules (`adapter-redis`,\n * `adapter-ioredis`) are lazy-imported so peer-deps you don't use stay out of\n * your bundle.\n */\n\nimport type {\n RedisClientFactory,\n RedisClientConfig,\n RedisClientLike,\n} from \"../../types.js\";\n\nexport async function buildClient(\n source: RedisClientFactory | RedisClientConfig\n): Promise<RedisClientLike> {\n if (typeof source === \"function\") {\n return await source();\n }\n switch (source.type) {\n case \"redis\": {\n const { adaptRedisV5, createRedisV5Client } = await import(\n \"./adapter-redis.js\"\n );\n return adaptRedisV5(createRedisV5Client(source));\n }\n case \"ioredis\": {\n const { adaptIoredis, createIoredisClient } = await import(\n \"./adapter-ioredis.js\"\n );\n return adaptIoredis(createIoredisClient(source));\n }\n case \"cluster\": {\n const { adaptCluster, createIoredisCluster } = await import(\n \"./adapter-ioredis.js\"\n );\n return adaptCluster(createIoredisCluster(source));\n }\n case \"sentinel\": {\n const { adaptIoredis, createIoredisSentinel } = await import(\n \"./adapter-ioredis.js\"\n );\n return adaptIoredis(createIoredisSentinel(source));\n }\n default: {\n const exhaustive: never = source;\n throw new Error(\n `[next-cache] unknown client config: ${JSON.stringify(exhaustive)}`\n );\n }\n }\n}\n\nexport interface ConnectionRetryOptions {\n /** Cooldown before the first retry after a failed connect (ms). Default 1000. */\n baseCooldownMs?: number;\n /** Upper bound for the exponential cooldown (ms). Default 30000. */\n maxCooldownMs?: number;\n}\n\n/**\n * Manage connect state without launching parallel connect calls. The reference\n * implementation's `connectPromise` pattern is preserved here.\n *\n * A failed connect does NOT latch the manager into a dead state: retries are\n * allowed after an exponential cooldown (base 1s, doubling per consecutive\n * failure, capped at 30s). During the cooldown `getOrConnect()` returns `null`\n * immediately so request paths fast-fail to the memory fallback instead of\n * queueing behind doomed connect attempts. A dropped connection (client\n * present but no longer open) is replaced with a fresh client on the next\n * call; the dead client is disposed best-effort.\n */\nexport class ConnectionManager {\n private client: RedisClientLike | null = null;\n private connecting: Promise<RedisClientLike | null> | null = null;\n private consecutiveFailures = 0;\n private lastFailureAt = 0;\n private readonly baseCooldownMs: number;\n private readonly maxCooldownMs: number;\n\n constructor(\n private readonly source: RedisClientFactory | RedisClientConfig,\n private readonly onError: (err: Error) => void,\n retry: ConnectionRetryOptions = {}\n ) {\n this.baseCooldownMs = retry.baseCooldownMs ?? 1000;\n this.maxCooldownMs = retry.maxCooldownMs ?? 30_000;\n }\n\n private cooldownMs(): number {\n if (this.consecutiveFailures === 0) return 0;\n return Math.min(\n this.maxCooldownMs,\n this.baseCooldownMs * 2 ** (this.consecutiveFailures - 1)\n );\n }\n\n async getOrConnect(): Promise<RedisClientLike | null> {\n if (this.client?.isOpen) return this.client;\n if (this.connecting) return this.connecting;\n if (Date.now() - this.lastFailureAt < this.cooldownMs()) return null;\n\n const stale = this.client;\n this.client = null;\n\n this.connecting = (async () => {\n disposeQuietly(stale);\n try {\n const c = await buildClient(this.source);\n c.on(\"error\", (err) => this.onError(err));\n if (!c.isOpen) await c.connect();\n this.client = c;\n this.consecutiveFailures = 0;\n return c;\n } catch (err) {\n this.consecutiveFailures += 1;\n this.lastFailureAt = Date.now();\n this.onError(err as Error);\n return null;\n } finally {\n this.connecting = null;\n }\n })();\n\n return this.connecting;\n }\n\n reset(): void {\n disposeQuietly(this.client);\n this.client = null;\n this.connecting = null;\n this.consecutiveFailures = 0;\n this.lastFailureAt = 0;\n }\n}\n\n/**\n * Close a replaced client so it stops reconnect loops and frees its socket.\n * The adapters expose `dispose`; raw clients passed via a factory may expose\n * `destroy` (redis@5) or `disconnect` (ioredis) instead.\n */\nfunction disposeQuietly(client: RedisClientLike | null): void {\n if (!client) return;\n const c = client as RedisClientLike & {\n destroy?: () => unknown;\n disconnect?: () => unknown;\n };\n try {\n (c.dispose ?? c.destroy ?? c.disconnect)?.call(c);\n } catch {\n // Best-effort: a client that fails to close is abandoned to GC.\n }\n}\n","/**\n * Default logger — `console`-backed at warn level and above. Keeps `info` /\n * `debug` quiet so the cache layer doesn't pollute production logs by default.\n *\n * Apps that want verbose tracing inject their own `Logger` via\n * `CacheHandlerOptions.logger`.\n */\n\nimport type { Logger } from \"../types.js\";\n\nexport const defaultLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: (message, meta) => {\n if (meta) console.warn(`[next-cache] ${message}`, meta);\n else console.warn(`[next-cache] ${message}`);\n },\n error: (message, meta) => {\n if (meta) console.error(`[next-cache] ${message}`, meta);\n else console.error(`[next-cache] ${message}`);\n },\n};\n","/**\n * Lua script loader. Handles the EVALSHA → NOSCRIPT → SCRIPT LOAD → EVALSHA\n * dance so the network round-trip cost is one packet on every call after the\n * first.\n *\n * The script bodies are imported as strings via tsup's `loader: { '.lua':\n * 'text' }` configuration. We compute their SHA1 lazily on first use rather\n * than pre-loading on connect — a connect handler that pre-loads scripts adds\n * a startup failure mode (Redis ACLs that block SCRIPT LOAD will surface as\n * connection errors) without a corresponding benefit.\n */\n\nimport { createHash } from \"node:crypto\";\n\nimport type { RedisClientLike } from \"../../types.js\";\n\nimport setWithTagsLua from \"./set-with-tags.lua\";\nimport revalidateHardLua from \"./revalidate-hard.lua\";\nimport refreshTagLockLua from \"./refresh-tag-lock.lua\";\n\nexport const SCRIPTS = {\n setWithTags: setWithTagsLua,\n revalidateHard: revalidateHardLua,\n refreshTagLock: refreshTagLockLua,\n} as const;\n\nexport type ScriptName = keyof typeof SCRIPTS;\n\nconst shaCache = new Map<ScriptName, string>();\n\nfunction sha1(body: string): string {\n return createHash(\"sha1\").update(body).digest(\"hex\");\n}\n\nfunction isNoScriptError(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n const msg = (err as { message?: string }).message ?? \"\";\n return msg.includes(\"NOSCRIPT\");\n}\n\n/**\n * Execute a named Lua script with EVALSHA, falling back to EVAL + SCRIPT LOAD\n * if the server doesn't have it cached (e.g. Redis was restarted).\n */\nexport async function execLuaScript<TResult = unknown>(\n client: RedisClientLike,\n name: ScriptName,\n keys: string[],\n args: string[]\n): Promise<TResult> {\n const body = SCRIPTS[name];\n let cachedSha = shaCache.get(name);\n if (cachedSha === undefined) {\n cachedSha = sha1(body);\n shaCache.set(name, cachedSha);\n }\n\n // Best path: EVALSHA. Most Redis servers will have the script cached after\n // the first EVAL.\n if (typeof client.evalSha === \"function\") {\n try {\n return (await client.evalSha(cachedSha, {\n keys,\n arguments: args,\n })) as TResult;\n } catch (err) {\n if (!isNoScriptError(err)) {\n // Some other failure — propagate.\n throw err;\n }\n // Fall through to EVAL.\n }\n }\n\n // EVAL ships the script body and primes the server cache. Subsequent\n // EVALSHA on this connection will succeed.\n return (await client.eval(body, { keys, arguments: args })) as TResult;\n}\n","-- set-with-tags.lua\n--\n-- Atomically write a cache entry and update the tag indices that point at it.\n-- Replaces the non-atomic SET → SADD → EXPIRE sequence in the reference\n-- implementation, which had a race window where another instance's hard\n-- invalidate could leave dangling tag members.\n--\n-- KEYS[1] : entry key (e.g. \"next-cache:entry:abc123\")\n-- KEYS[2..N] : tag set keys (e.g. \"next-cache:tag:posts\")\n-- ARGV[1] : serialized entry payload\n-- ARGV[2] : entry TTL in seconds\n-- ARGV[3] : tag TTL in seconds (typically same as entry TTL)\n-- ARGV[4] : tag count (number of KEYS after KEYS[1])\n--\n-- Returns: 1 on success.\n\nlocal entryKey = KEYS[1]\nlocal payload = ARGV[1]\nlocal entryTtl = tonumber(ARGV[2])\nlocal tagTtl = tonumber(ARGV[3])\nlocal tagCount = tonumber(ARGV[4])\n\nredis.call('SET', entryKey, payload, 'EX', entryTtl)\n\nfor i = 1, tagCount do\n local tagKey = KEYS[i + 1]\n redis.call('SADD', tagKey, entryKey)\n -- EXPIRE on every SADD: ensures the tag set never outlives its entries\n -- and survives at least as long as the longest associated entry.\n redis.call('EXPIRE', tagKey, tagTtl)\nend\n\nreturn 1\n","-- revalidate-hard.lua\n--\n-- Atomically remove every entry referenced by a tag and stamp the tag's\n-- expiration marker. Used by `updateTags(tags, { expire: 0 })` — the hard\n-- invalidation path triggered by `updateTag()` server actions in Next.js 16.\n--\n-- KEYS[1] : tag set key (e.g. \"next-cache:tag:posts\")\n-- KEYS[2] : tag-expiration marker key (e.g. \"next-cache:tag-expiration:posts\")\n-- ARGV[1] : current timestamp in milliseconds\n-- ARGV[2] : marker TTL in seconds (default: 1 day so cross-deployment\n-- readers can still observe the invalidation)\n--\n-- Returns: number of entries that were deleted.\n\nlocal tagKey = KEYS[1]\nlocal markerKey = KEYS[2]\nlocal nowMs = ARGV[1]\nlocal markerTtl = tonumber(ARGV[2])\n\nlocal entries = redis.call('SMEMBERS', tagKey)\nlocal deleted = 0\n\nif #entries > 0 then\n -- DEL accepts varargs; unpack the entry list.\n redis.call('DEL', unpack(entries))\n deleted = #entries\nend\n\n-- Drop the tag set itself; on next SET it'll be recreated by set-with-tags.\nredis.call('DEL', tagKey)\n\n-- Stamp the invalidation timestamp. Readers compare this against an entry's\n-- timestamp inside `getExpiration` to decide whether soft-tag-only entries\n-- should be considered stale.\nredis.call('SET', markerKey, nowMs, 'EX', markerTtl)\n\nreturn deleted\n","-- refresh-tag-lock.lua\n--\n-- Single-flight lock acquisition for background refresh.\n-- Reserved for v0.2's stampede-protection feature. Currently unused by the\n-- handler runtime, but bundled so v0.2 can ship without a major bump.\n--\n-- KEYS[1] : lock key (e.g. \"next-cache:lock:abc123\")\n-- ARGV[1] : owner identifier (instance id; written for observability)\n-- ARGV[2] : lock TTL in seconds (10s recommended — long enough for refresh\n-- to complete, short enough to recover from a crashed owner)\n--\n-- Returns: 1 if lock acquired, 0 if another owner already holds it.\n\nlocal lockKey = KEYS[1]\nlocal owner = ARGV[1]\nlocal ttl = tonumber(ARGV[2])\n\nif redis.call('GET', lockKey) then\n return 0\nend\n\nredis.call('SET', lockKey, owner, 'EX', ttl)\nreturn 1\n","/**\n * In-memory cache stores with proper TTL handling.\n *\n * The reference implementation in next-redis-cache-demo had a subtle leak:\n * when the memory fallback was activated, `getMemoryTagSet(tag).add(redisKey)`\n * stored entries indefinitely because no `setTimeout` was registered to clean\n * them up. This implementation fixes that by attaching an `unref()`-ed timer\n * to every keyed value.\n *\n * Why two classes:\n * - `MemoryStore<T>` mirrors Redis SET/GET/DEL with EX semantics\n * - `MemorySetStore` mirrors SADD/SMEMBERS/EXPIRE for tag indices\n */\n\ninterface MemoryEntry<T> {\n value: T;\n expiresAt: number;\n}\n\n/**\n * Node's setTimeout coerces delays to a 32-bit signed integer. Anything\n * beyond ~24.85 days fires immediately with a TimeoutOverflowWarning. We cap\n * scheduled timers at this safe maximum and rely on the lazy `expiresAt`\n * check inside `get()` for the rest. Useful for the 1-year TTL fallback that\n * `cacheLife({expire: Infinity})` resolves to.\n */\nconst MAX_TIMER_MS = 2_147_483_647; // 2^31 - 1, ~24.85 days\nfunction clampTimerMs(ms: number): number {\n return Math.min(Math.max(0, ms), MAX_TIMER_MS);\n}\n\n/**\n * Default entry cap for the fallback stores. The fallback exists to ride out\n * a Redis outage, not to replace it — an unbounded map filled by a long\n * outage on a busy site is an OOM waiting to happen.\n */\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport class MemoryStore<T> {\n private readonly kv = new Map<string, MemoryEntry<T>>();\n private readonly timers = new Map<string, ReturnType<typeof setTimeout>>();\n private readonly maxEntries: number;\n\n constructor(maxEntries: number = DEFAULT_MAX_ENTRIES) {\n this.maxEntries = Math.max(1, maxEntries);\n }\n\n set(key: string, value: T, ttlSeconds: number): void {\n this.delete(key);\n const expiresAt = Date.now() + ttlSeconds * 1000;\n this.kv.set(key, { value, expiresAt });\n const timer = setTimeout(() => this.delete(key), clampTimerMs(ttlSeconds * 1000));\n if (typeof timer === \"object\" && \"unref\" in timer) {\n (timer as { unref: () => void }).unref();\n }\n this.timers.set(key, timer);\n // LRU eviction: Map preserves insertion order and get() re-inserts on\n // hit, so the first key is always the least recently used.\n while (this.kv.size > this.maxEntries) {\n const oldest = this.kv.keys().next().value as string;\n this.delete(oldest);\n }\n }\n\n get(key: string): T | null {\n const entry = this.kv.get(key);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n this.delete(key);\n return null;\n }\n // Refresh recency for LRU ordering.\n this.kv.delete(key);\n this.kv.set(key, entry);\n return entry.value;\n }\n\n delete(key: string): boolean {\n const timer = this.timers.get(key);\n if (timer !== undefined) {\n clearTimeout(timer);\n this.timers.delete(key);\n }\n return this.kv.delete(key);\n }\n\n has(key: string): boolean {\n return this.get(key) !== null;\n }\n\n keys(): string[] {\n const now = Date.now();\n const live: string[] = [];\n for (const [key, entry] of this.kv.entries()) {\n if (entry.expiresAt >= now) live.push(key);\n }\n return live;\n }\n\n size(): number {\n return this.keys().length;\n }\n\n clear(): void {\n for (const timer of this.timers.values()) clearTimeout(timer);\n this.timers.clear();\n this.kv.clear();\n }\n}\n\n/**\n * Set-of-strings store with per-set TTL. Mirrors Redis SADD / SMEMBERS / EXPIRE.\n *\n * TTL semantics: EXPIRE replaces the previous TTL. We schedule one timer per\n * set (not per member) and reset it on every SADD or EXPIRE.\n */\nexport class MemorySetStore {\n private readonly sets = new Map<string, Set<string>>();\n private readonly expiresAt = new Map<string, number>();\n private readonly timers = new Map<string, ReturnType<typeof setTimeout>>();\n private readonly maxSets: number;\n\n constructor(maxSets: number = DEFAULT_MAX_ENTRIES) {\n this.maxSets = Math.max(1, maxSets);\n }\n\n sAdd(key: string, member: string | string[]): number {\n const members = Array.isArray(member) ? member : [member];\n let set = this.sets.get(key);\n if (!set) {\n set = new Set();\n } else {\n // Refresh recency for LRU ordering.\n this.sets.delete(key);\n }\n this.sets.set(key, set);\n let added = 0;\n for (const m of members) {\n if (!set.has(m)) {\n set.add(m);\n added += 1;\n }\n }\n while (this.sets.size > this.maxSets) {\n const oldest = this.sets.keys().next().value as string;\n this.delete(oldest);\n }\n return added;\n }\n\n sMembers(key: string): string[] {\n if (this.isExpired(key)) {\n this.delete(key);\n return [];\n }\n const set = this.sets.get(key);\n return set ? Array.from(set) : [];\n }\n\n expire(key: string, ttlSeconds: number): boolean {\n if (!this.sets.has(key)) return false;\n const prev = this.timers.get(key);\n if (prev !== undefined) clearTimeout(prev);\n const expiresAt = Date.now() + ttlSeconds * 1000;\n this.expiresAt.set(key, expiresAt);\n const timer = setTimeout(() => this.delete(key), clampTimerMs(ttlSeconds * 1000));\n if (typeof timer === \"object\" && \"unref\" in timer) {\n (timer as { unref: () => void }).unref();\n }\n this.timers.set(key, timer);\n return true;\n }\n\n delete(key: string): boolean {\n const timer = this.timers.get(key);\n if (timer !== undefined) {\n clearTimeout(timer);\n this.timers.delete(key);\n }\n this.expiresAt.delete(key);\n return this.sets.delete(key);\n }\n\n keys(): string[] {\n const live: string[] = [];\n for (const key of this.sets.keys()) {\n if (!this.isExpired(key)) live.push(key);\n }\n return live;\n }\n\n clear(): void {\n for (const timer of this.timers.values()) clearTimeout(timer);\n this.timers.clear();\n this.expiresAt.clear();\n this.sets.clear();\n }\n\n private isExpired(key: string): boolean {\n const at = this.expiresAt.get(key);\n return at !== undefined && Date.now() > at;\n }\n}\n","/**\n * Process-local metric counters with an optional emit hook.\n *\n * Two layers:\n * 1. Always-on counter accumulation (free for app-side `getMetricSnapshot()`)\n * 2. Optional `onMetric` callback for OpenTelemetry / StatsD / Datadog\n * forwarding (no transitive deps in this package)\n *\n * Cardinality discipline: callers pass low-cardinality `meta` (e.g. operation\n * name, freshness bucket). Cache keys and tag names are never emitted.\n */\n\nimport type { MetricEmitter, MetricEvent, MetricEventType } from \"../types.js\";\n\ninterface Counter {\n count: number;\n totalMs: number;\n lastTs: number;\n}\n\nconst counters = new Map<MetricEventType, Counter>();\n\nfunction bump(event: MetricEvent): void {\n const existing = counters.get(event.type);\n if (existing) {\n existing.count += 1;\n if (event.ms !== undefined) existing.totalMs += event.ms;\n existing.lastTs = Date.now();\n return;\n }\n counters.set(event.type, {\n count: 1,\n totalMs: event.ms ?? 0,\n lastTs: Date.now(),\n });\n}\n\n/** Bind the user-supplied emitter, return a curried emit function. */\nexport function createEmitter(onMetric?: MetricEmitter): MetricEmitter {\n return (event: MetricEvent) => {\n bump(event);\n if (onMetric) {\n try {\n onMetric(event);\n } catch {\n // Telemetry must never crash the cache layer.\n }\n }\n };\n}\n\n/** Snapshot of current counters. Useful for `/api/metrics` style endpoints. */\nexport function getMetricSnapshot(): Record<\n MetricEventType,\n { count: number; avgMs: number; lastTs: number } | undefined\n> {\n const out: Partial<\n Record<MetricEventType, { count: number; avgMs: number; lastTs: number }>\n > = {};\n for (const [type, c] of counters.entries()) {\n out[type] = {\n count: c.count,\n avgMs: c.count > 0 ? c.totalMs / c.count : 0,\n lastTs: c.lastTs,\n };\n }\n return out as Record<\n MetricEventType,\n { count: number; avgMs: number; lastTs: number } | undefined\n >;\n}\n\n/** Reset counters. Test-only export; not part of the public API. */\nexport function __resetMetricsForTest(): void {\n counters.clear();\n}\n","/**\n * Build namespace resolution.\n *\n * Why this matters: the reference implementation's \"static chunk 404\" incident\n * was caused by old prerender HTML from a previous deployment hitting in Redis.\n * Two deployments shared the same cache key prefix, so a new build's request\n * could deserialize an entry that referenced static chunks deleted by the\n * deployment swap.\n *\n * Embedding a per-deployment namespace into every entry key fixes this:\n * next-incremental:entry:<commit-sha>:<path>\n *\n * Rolling forward to a new SHA invalidates everything atomically without\n * needing a manual flush. Tags remain shared across deployments so\n * `revalidateTag()` keeps cross-deployment semantics.\n */\n\nconst FALLBACK = \"unversioned\";\n\n/**\n * Resolve the namespace value. Pure helper used at runtime when constructing\n * keys.\n */\nexport function resolveBuildNamespace(\n override?: string | (() => string)\n): string {\n if (override !== undefined) {\n return typeof override === \"function\" ? override() : override;\n }\n return (\n process.env.DEPLOYMENT_VERSION ??\n process.env.GIT_HASH ??\n process.env.NEXT_DEPLOYMENT_ID ??\n FALLBACK\n );\n}\n\n/**\n * Build a namespaced key. When `hashTag` is true, the namespace is wrapped in\n * `{}` so multi-key Lua scripts on Redis Cluster all hash to the same slot.\n *\n * Example:\n * buildKey(\"next-incremental:entry:\", \"ns42\", \"/blog/hello\", false)\n * → \"next-incremental:entry:ns42:/blog/hello\"\n * buildKey(\"next-cache:tag:\", \"ns42\", \"post-1\", true)\n * → \"next-cache:tag:{ns42}:post-1\"\n */\nexport function buildKey(\n prefix: string,\n namespace: string,\n rest: string,\n hashTag = false\n): string {\n const ns = hashTag ? `{${namespace}}` : namespace;\n return `${prefix}${ns}:${rest}`;\n}\n","/**\n * Detect whether Next.js is in the production build phase.\n *\n * During `next build` (or `next start --build`), Next pre-renders pages with\n * `'use cache'` directives, which means it calls `cacheHandlers.get` / `.set`\n * before any runtime infrastructure exists. Connecting to Redis in this phase\n * blows up the build with ECONNREFUSED.\n *\n * This is the same root cause that left `@fortedigital/nextjs-cache-handler`\n * PR #207 stalled for 3+ months — the maintainer's review explicitly demanded\n * `PHASE_PRODUCTION_BUILD` handling.\n *\n * The constant value comes from `next/constants`:\n * PHASE_PRODUCTION_BUILD = 'phase-production-build'\n *\n * We intentionally read process.env at call time (not import time) so tests\n * and apps that set NEXT_PHASE late still observe the change.\n */\nconst PHASE_PRODUCTION_BUILD = \"phase-production-build\";\n\nexport function isBuildPhase(): boolean {\n return process.env.NEXT_PHASE === PHASE_PRODUCTION_BUILD;\n}\n\n/**\n * Decide whether to attempt a Redis connection given the configured fallback\n * strategy. Used as the gate at the top of every handler method.\n *\n * Returns `false` ⇒ skip Redis entirely, route through the in-memory fallback\n * Returns `true` ⇒ proceed with the configured client\n */\nexport function shouldUseRedis(opts: {\n fallback?: \"auto\" | \"always\" | \"never\";\n isBuildPhase?: () => boolean;\n}): boolean {\n if (opts.fallback === \"always\") return false;\n const detector = opts.isBuildPhase ?? isBuildPhase;\n if (detector()) return false;\n return true;\n}\n","/**\n * ReadableStream <-> base64 conversion for the cacheHandlers value field.\n *\n * Per the Next 16 spec (docs/next16-spec.md §2.2):\n * value: ReadableStream<Uint8Array>\n *\n * Redis stores strings, so we materialize the stream into a Buffer, encode as\n * base64, persist as part of a JSON envelope, then reconstruct a single-chunk\n * ReadableStream on read.\n *\n * Spec-mandated behavior on partial writes:\n * \"the stream may error partway through rendering. Your handler should\n * decide whether to keep partial entries or discard them. Discarding is\n * safer.\"\n * → readStreamFully throws on stream errors. The caller must catch and skip\n * the SET operation when this throws.\n */\n\nexport async function readStreamFully(\n stream: ReadableStream<Uint8Array>\n): Promise<Buffer> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n try {\n \n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n return Buffer.concat(chunks.map((c) => Buffer.from(c)));\n}\n\nexport function bufferToStream(buf: Buffer): ReadableStream<Uint8Array> {\n // Capture once; the controller's enqueue copy isn't necessary because the\n // backing Buffer is owned by us at this point.\n return new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(new Uint8Array(buf));\n controller.close();\n },\n });\n}\n\nexport interface StoredEntryEnvelope {\n /** base64-encoded stream contents */\n value: string;\n tags: string[];\n stale: number;\n timestamp: number;\n expire: number;\n revalidate: number;\n}\n\nexport function encodeEnvelope(\n buf: Buffer,\n meta: Omit<StoredEntryEnvelope, \"value\">\n): string {\n const envelope: StoredEntryEnvelope = {\n value: buf.toString(\"base64\"),\n ...meta,\n };\n return JSON.stringify(envelope);\n}\n\nexport function decodeEnvelope(raw: string): StoredEntryEnvelope | null {\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (\n !parsed ||\n typeof parsed !== \"object\" ||\n typeof (parsed as StoredEntryEnvelope).value !== \"string\"\n ) {\n return null;\n }\n return parsed as StoredEntryEnvelope;\n } catch {\n return null;\n }\n}\n","/**\n * Stale-While-Revalidate decision logic for the cacheHandlers (plural)\n * interface.\n *\n * Next.js 16 distinguishes three time axes for an entry, all expressed as\n * seconds offset from `timestamp` (ms epoch):\n *\n * timestamp ───── revalidate ───── stale ───── expire ─────►\n * │ │ │ │\n * fresh SWR window SWR window hard\n * │ (background ends miss\n * │ refresh)\n *\n * The reference handler in next-redis-cache-demo collapsed this into a single\n * `revalidate` check, returning `undefined` (cache miss) the moment the entry\n * crossed `revalidate`. That defeats SWR — every user past the revalidate\n * boundary pays the full origin cost instead of getting an instant stale read.\n *\n * The corrected partition:\n * - age <= revalidate * 1000 → \"fresh\"\n * - revalidate*1000 < age <= expire*1000 → \"stale\" (still served, refresh\n * happens in background per Next.js' own scheduling)\n * - age > expire*1000 → \"expired\" (true miss, evict the entry)\n *\n * This module is pure logic. It does not touch Redis. The handler's `get`\n * threads the entry through `partitionEntry` and decides what to return.\n */\n\nimport type { CacheComponentsEntry } from \"../types.js\";\n\nexport type EntryFreshness = \"fresh\" | \"stale\" | \"expired\";\n\nexport interface PartitionResult {\n freshness: EntryFreshness;\n /** Age in ms since the entry's timestamp. */\n ageMs: number;\n}\n\nconst SECOND_MS = 1000;\n\n/**\n * Classify an entry into one of the three freshness buckets.\n *\n * Edge cases:\n * - Negative age (clock skew where timestamp is in the future): treat as fresh.\n * The entry was clearly just written; we don't punish the read for a 2s\n * clock drift between the writer and reader instances.\n * - expire === 0: per Next.js' \"no hard expire\" sentinel. We map it to a\n * practical upper bound (one year) so the partition still works. This\n * matches the TTL-fallback behavior of the reference handler.\n * - revalidate >= expire: degenerate config. We honor revalidate as the\n * fresh→stale boundary and clamp expire upward when it's smaller.\n */\nexport function partitionEntry(\n entry: Pick<CacheComponentsEntry, \"timestamp\" | \"revalidate\" | \"expire\">,\n now: number = Date.now()\n): PartitionResult {\n const ageMs = now - entry.timestamp;\n\n if (ageMs < 0) {\n return { freshness: \"fresh\", ageMs };\n }\n\n const revalidateMs = Math.max(0, entry.revalidate) * SECOND_MS;\n const rawExpireMs = entry.expire === 0 ? Number.POSITIVE_INFINITY : Math.max(0, entry.expire) * SECOND_MS;\n const expireMs = Math.max(rawExpireMs, revalidateMs);\n\n if (ageMs <= revalidateMs) {\n return { freshness: \"fresh\", ageMs };\n }\n if (ageMs <= expireMs) {\n return { freshness: \"stale\", ageMs };\n }\n return { freshness: \"expired\", ageMs };\n}\n\n/**\n * Decide whether to honor a `staleWhileRevalidate` config knob. When the user\n * disables SWR, \"stale\" entries are treated as expired (preserving v0\n * behavior).\n */\nexport function shouldServeStale(\n result: PartitionResult,\n staleWhileRevalidate: boolean\n): boolean {\n return result.freshness === \"fresh\" || (result.freshness === \"stale\" && staleWhileRevalidate);\n}\n","/**\n * `cacheHandler` (singular) entry point — for Pages Router ISR and on-demand\n * revalidation. See docs/next16-spec.md §3.\n *\n * Usage:\n *\n * // cache-incremental.config.ts\n * import { createIncrementalCacheHandler } from \"@leejpsd/nextjs-cache-handler/incremental\";\n * module.exports = createIncrementalCacheHandler({\n * client: { type: \"redis\", url: process.env.REDIS_URL! },\n * buildNamespace: process.env.DEPLOYMENT_VERSION,\n * });\n *\n * // next.config.ts\n * const nextConfig = {\n * cacheHandler: require.resolve(\"./cache-incremental.config.ts\"),\n * cacheMaxMemorySize: 0, // delegate entirely to this handler\n * };\n */\n\nexport {\n createIncrementalCacheHandler,\n IncrementalRedisCacheHandler,\n} from \"./handler.js\";\nexport type { IncrementalCtx } from \"./handler.js\";\n","/**\n * Spec-compliant `cacheHandler` (singular) implementation. See\n * docs/next16-spec.md §3.\n *\n * Used for:\n * - Pages Router ISR\n * - On-demand ISR (`res.revalidate`, `x-prerender-revalidate`)\n * - `fetch(..., { next: { tags } })` cache (kind: FETCH)\n * - App Router page/route HTML (when not using `'use cache'`)\n *\n * Differs from cache-components handler in two important ways:\n * 1. `value` is a plain Buffer/string, not a stream\n * 2. Tag invalidation is encoded as `{stale, expired}` payloads stored at\n * `next-incremental:tag:<tag>` (no namespace prefix — tags are shared\n * across deployments by design so revalidateTag survives a deploy)\n */\n\nimport { CacheTimeoutError, withAbortSignal } from \"../shared/abort.js\";\nimport { compressValue, decompressValue } from \"../shared/compress.js\";\nimport { ConnectionManager } from \"../shared/client/index.js\";\nimport { defaultLogger } from \"../shared/logger.js\";\nimport { MemoryStore } from \"../shared/memory-fallback.js\";\nimport { createEmitter } from \"../shared/metrics.js\";\nimport { buildKey, resolveBuildNamespace } from \"../shared/namespace.js\";\nimport { shouldUseRedis } from \"../shared/build-phase.js\";\nimport type {\n CacheHandlerOptions,\n IncrementalCacheData,\n Logger,\n MetricEmitter,\n} from \"../types.js\";\n\nimport {\n deserializeCacheRecord,\n serializeCacheRecord,\n} from \"./serialize.js\";\n\n// ─── Defaults ────────────────────────────────────────────────────────────────\n\nconst DEFAULT_KEY_PREFIX = \"next-incremental:\";\nconst ENTRY_SUFFIX = \"entry:\";\nconst TAG_SUFFIX = \"tag:\";\nconst INSTANCE_LOCAL_TAG_PREFIX = \"instance-local:\";\nconst ONE_YEAR_SEC = 60 * 60 * 24 * 365;\nconst MIN_TTL_SEC = 60;\nconst DEFAULT_ABORT_MS = 1500;\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface IncrementalCtx {\n kind?: string;\n /** Next 15 passes a lowercase kind hint (\"fetch\" | \"app\" | \"pages\"). */\n kindHint?: string;\n tags?: string[];\n softTags?: string[];\n revalidatedTags?: string[];\n /** Next 16 shape. */\n cacheControl?: { revalidate?: number | false };\n /** Next 15 shape — revalidate sits directly on the ctx. */\n revalidate?: number | false;\n fetchCache?: boolean;\n}\n\ninterface CacheRecord {\n lastModified: number;\n value: IncrementalCacheData[\"value\"];\n /** Route/entry revalidate window (seconds) captured at set() time — lets\n * get() compute a precise SWR backdate for soft tag invalidations. */\n revalidateSec?: number;\n}\n\ninterface TagState {\n /** Last revalidate timestamp (ms). Soft — only fetch entries treat this as expired. */\n stale?: number;\n /** Hard expiration timestamp (ms). All entry kinds treat this as expired. */\n expired?: number;\n}\n\n// ─── State ───────────────────────────────────────────────────────────────────\n\ninterface HandlerState {\n opts: Required<\n Pick<\n CacheHandlerOptions,\n \"abortTimeoutMs\" | \"fallback\" | \"hashTag\" | \"keyPrefix\"\n >\n > & { rest: CacheHandlerOptions };\n logger: Logger;\n emit: MetricEmitter;\n conn: ConnectionManager;\n memEntries: MemoryStore<string>;\n /** Tag states, by bare tag (no namespace prefix — see tagMetaKey comment). */\n memTagStates: Map<string, TagState>;\n resolveNs: () => string;\n}\n\nfunction gateRedis(state: HandlerState): boolean {\n const fb = state.opts.fallback;\n const ibp = state.opts.rest.isBuildPhase;\n return ibp ? shouldUseRedis({ fallback: fb, isBuildPhase: ibp }) : shouldUseRedis({ fallback: fb });\n}\n\nfunction gateRedisInit(state: HandlerState): boolean {\n return gateRedis(state);\n}\n\nfunction init(opts: CacheHandlerOptions): HandlerState {\n const logger = opts.logger ?? defaultLogger;\n const emit = createEmitter(opts.onMetric);\n const conn = new ConnectionManager(opts.client, (err) => {\n logger.warn(\"Redis client error (incremental)\", { message: err.message });\n emit({ type: \"redis.connect.failed\", meta: { message: err.message } });\n });\n return {\n opts: {\n abortTimeoutMs: opts.abortTimeoutMs ?? DEFAULT_ABORT_MS,\n fallback: opts.fallback ?? \"auto\",\n hashTag: opts.hashTag ?? false,\n keyPrefix: opts.keyPrefix ?? DEFAULT_KEY_PREFIX,\n rest: opts,\n },\n logger,\n emit,\n conn,\n memEntries: new MemoryStore<string>(opts.memoryMaxEntries),\n memTagStates: new Map(),\n resolveNs: () => resolveBuildNamespace(opts.buildNamespace),\n };\n}\n\n// ─── Key helpers ─────────────────────────────────────────────────────────────\n\nfunction entryKey(state: HandlerState, cacheKey: string): string {\n // Entries ARE namespaced by build — the whole point of BUILD_NAMESPACE.\n return buildKey(\n `${state.opts.keyPrefix}${ENTRY_SUFFIX}`,\n state.resolveNs(),\n cacheKey,\n state.opts.hashTag\n );\n}\n\nfunction tagMetaKey(state: HandlerState, tag: string): string {\n // Tag states are intentionally NOT namespaced. revalidateTag should be\n // observable from new deployments too (otherwise a deploy-time invalidation\n // is lost). See incremental-cache-handler.js comment in reference impl.\n return `${state.opts.keyPrefix}${TAG_SUFFIX}${tag}`;\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction normalizeTags(tags: unknown): string[] {\n return Array.isArray(tags)\n ? tags.filter((t): t is string => typeof t === \"string\" && t.length > 0)\n : [];\n}\n\nfunction shouldUseLocalIncrementalStore(tags: string[]): boolean {\n return tags.some((t) => t.startsWith(INSTANCE_LOCAL_TAG_PREFIX));\n}\n\nfunction extractTagsFromValue(\n value: IncrementalCacheData[\"value\"],\n ctx: IncrementalCtx | undefined\n): string[] {\n if (!value || typeof value !== \"object\") return [];\n const v = value as { kind?: string; tags?: unknown; headers?: Record<string, unknown> };\n\n if (v.kind === \"FETCH\") {\n return normalizeTags([\n ...normalizeTags(v.tags),\n ...normalizeTags(ctx?.tags),\n ...normalizeTags(ctx?.softTags),\n ]);\n }\n\n const headers = v.headers;\n if (!headers) return [];\n const tagsHeader = headers[\"x-next-cache-tags\"];\n if (typeof tagsHeader === \"string\") {\n return tagsHeader\n .split(\",\")\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n }\n if (Array.isArray(tagsHeader)) {\n return tagsHeader\n .flatMap((part) => String(part).split(\",\"))\n .map((t) => t.trim())\n .filter((t) => t.length > 0);\n }\n return [];\n}\n\nfunction isTagStateExpired(\n state: TagState | null,\n lastModified: number | undefined,\n isFetch: boolean\n): boolean {\n if (!state || typeof lastModified !== \"number\") return false;\n if (typeof state.expired === \"number\" && state.expired >= lastModified) return true;\n if (isFetch && typeof state.stale === \"number\" && state.stale >= lastModified) return true;\n return false;\n}\n\nfunction normalizeTtlSeconds(\n data: IncrementalCacheData[\"value\"],\n ctx: IncrementalCtx | undefined\n): number {\n if (data && typeof data === \"object\") {\n const d = data as { kind?: string; revalidate?: number | false };\n if (d.kind === \"FETCH\") {\n if (typeof d.revalidate === \"number\" && d.revalidate > 0) {\n return Math.min(Math.max(Math.ceil(d.revalidate), MIN_TTL_SEC), ONE_YEAR_SEC);\n }\n return ONE_YEAR_SEC;\n }\n }\n // Next 16 nests revalidate under cacheControl; Next 15 passes it directly.\n const revalidate = ctx?.cacheControl?.revalidate ?? ctx?.revalidate;\n if (revalidate === false || revalidate === undefined) return ONE_YEAR_SEC;\n if (typeof revalidate === \"number\" && revalidate > 0) {\n return Math.min(Math.max(Math.ceil(revalidate), MIN_TTL_SEC), ONE_YEAR_SEC);\n }\n return MIN_TTL_SEC;\n}\n\nasync function readTagStates(\n state: HandlerState,\n tags: string[]\n): Promise<(TagState | null)[]> {\n if (tags.length === 0) return [];\n\n const useRedis = gateRedisInit(state);\n if (!useRedis) {\n return tags.map((t) => state.memTagStates.get(t) ?? null);\n }\n\n try {\n return await withAbortSignal(\n \"incremental.readTagStates\",\n state.opts.abortTimeoutMs,\n async () => {\n const client = await state.conn.getOrConnect();\n if (!client) return tags.map((t) => state.memTagStates.get(t) ?? null);\n const values = await client.mGet(tags.map((t) => tagMetaKey(state, t)));\n return values.map((v) => {\n if (!v) return null;\n try {\n return JSON.parse(v) as TagState;\n } catch {\n return null;\n }\n });\n }\n );\n } catch {\n return tags.map((t) => state.memTagStates.get(t) ?? null);\n }\n}\n\n// ─── Handler class ──────────────────────────────────────────────────────────\n\nexport class IncrementalRedisCacheHandler {\n private readonly state: HandlerState;\n private readonly revalidatedTags: string[];\n /**\n * Request-scoped memo of Redis entry reads. Next.js instantiates this class\n * per request (and calls resetRequestCache() at request boundaries when it\n * reuses an instance), so entries live at most one request. Bounded by the\n * number of distinct cache keys a single request touches.\n */\n private readonly requestMemo = new Map<string, Promise<string | null>>();\n\n constructor(state: HandlerState, ctx?: { revalidatedTags?: string[] }) {\n this.state = state;\n this.revalidatedTags = normalizeTags(ctx?.revalidatedTags);\n }\n\n /**\n * Redis entry read, deduplicated per request: parallel RSC renders or\n * repeated fetch() calls hitting the same cache key share one GET. The\n * memoized promise never rejects — errors are converted to a miss (with\n * the same timeout metric the inline path emitted before).\n */\n private readEntryDeduped(eKey: string): Promise<string | null> {\n const memoized = this.requestMemo.get(eKey);\n if (memoized) {\n this.state.emit({ type: \"cache.get.deduped\" });\n return memoized;\n }\n const read = withAbortSignal(\n \"incremental.get\",\n this.state.opts.abortTimeoutMs,\n async () => {\n const client = await this.state.conn.getOrConnect();\n if (!client) return null;\n // Decompress inside the memoized promise so deduped callers don't\n // repeat the CPU work. Corrupt data rejects → miss via the catch.\n return await decompressValue(await client.get(eKey));\n }\n ).catch((err: unknown) => {\n if (err instanceof CacheTimeoutError) {\n this.state.emit({\n type: \"redis.timeout\",\n meta: { op: \"incremental.get\" },\n });\n }\n return null;\n });\n this.requestMemo.set(eKey, read);\n return read;\n }\n\n async get(\n cacheKey: string,\n ctx?: IncrementalCtx\n ): Promise<(CacheRecord & { tags?: string[] }) | null> {\n try {\n const requestedTags = normalizeTags([\n ...(ctx?.tags ?? []),\n ...(ctx?.softTags ?? []),\n ]);\n const useLocal = shouldUseLocalIncrementalStore(requestedTags);\n const eKey = entryKey(this.state, cacheKey);\n\n const useRedis =\n !useLocal &&\n gateRedis(this.state);\n\n let raw: string | null = null;\n if (useRedis) {\n raw = await this.readEntryDeduped(eKey);\n }\n // Memory is a fallback (or the primary store for instance-local tags);\n // `fallback: \"never\"` surfaces Redis unavailability as a miss instead.\n if (raw === null && (useLocal || this.state.opts.fallback !== \"never\")) {\n raw = this.state.memEntries.get(eKey);\n }\n if (raw === null) {\n this.state.emit({ type: \"cache.miss\" });\n return null;\n }\n\n const parsed = deserializeCacheRecord<CacheRecord>(raw);\n if (!parsed || typeof parsed !== \"object\" || !parsed.value) return null;\n\n const tags = extractTagsFromValue(parsed.value, ctx);\n if (tags.some((t) => this.revalidatedTags.includes(t))) {\n this.state.emit({ type: \"cache.miss\", meta: { reason: \"revalidated-this-request\" } });\n return null;\n }\n\n const tagStates = await readTagStates(this.state, tags);\n // Next 16 sends kind: \"FETCH\"; Next 15 sends kindHint: \"fetch\". The\n // stored value's own kind covers entries read without a hint.\n const isFetch =\n ctx?.kind === \"FETCH\" ||\n ctx?.kindHint?.toLowerCase() === \"fetch\" ||\n (typeof parsed.value === \"object\" &&\n parsed.value !== null &&\n (parsed.value as { kind?: string }).kind === \"FETCH\");\n if (tagStates.some((s) => isTagStateExpired(s, parsed.lastModified, isFetch))) {\n this.state.emit({ type: \"cache.miss\", meta: { reason: \"tag-state-expired\" } });\n return null;\n }\n\n // Soft (SWR) tag invalidation for non-fetch entries: a route's HTML must\n // not keep serving as FRESH after revalidateTag(tag, \"max\") — but it\n // shouldn't block either. Backdate lastModified just past the entry's\n // own revalidate window (captured at set() time) so Next serves it\n // stale and regenerates in the background — which also re-executes any\n // 'use cache' functions inside the route (the outer-layer half of #1;\n // fetch entries already treat `stale` as expired above). Backdating\n // further would cross the route's `expire` and turn SWR into a\n // blocking re-render.\n let lastModified = parsed.lastModified;\n if (!isFetch && typeof lastModified === \"number\") {\n const softTs = Math.max(\n 0,\n ...tagStates.map((s) =>\n s && typeof s.stale === \"number\" ? s.stale : 0\n )\n );\n if (softTs >= lastModified) {\n const rev = parsed.revalidateSec;\n if (typeof rev !== \"number\" || rev <= 0 || rev >= ONE_YEAR_SEC) {\n // No usable SWR window (revalidate: false, or a pre-upgrade\n // record without revalidateSec) — degrade to a blocking miss so\n // the invalidation still takes effect.\n this.state.emit({\n type: \"cache.miss\",\n meta: { reason: \"tag-invalidated\" },\n });\n return null;\n }\n lastModified = Math.min(\n lastModified,\n Date.now() - (rev + 1) * 1000\n );\n this.state.emit({\n type: \"cache.stale\",\n meta: { reason: \"tag-invalidated\" },\n });\n }\n }\n\n this.state.emit({ type: \"cache.hit\" });\n return { ...parsed, lastModified, tags };\n } catch (err) {\n this.state.logger.error(\"get() unexpected error\", {\n message: (err as Error).message,\n });\n return null;\n }\n }\n\n async set(\n cacheKey: string,\n data: IncrementalCacheData[\"value\"],\n ctx?: IncrementalCtx\n ): Promise<void> {\n if (!data) return;\n try {\n const tags = extractTagsFromValue(data, ctx);\n const useLocal = shouldUseLocalIncrementalStore(tags);\n const ttl = normalizeTtlSeconds(data, ctx);\n const record: CacheRecord = {\n lastModified: Date.now(),\n value: data,\n revalidateSec: ttl,\n };\n const serialized = serializeCacheRecord(record);\n const eKey = entryKey(this.state, cacheKey);\n // The stored value changes — a memoized read (including a memoized\n // miss) must not shadow it for the rest of the request.\n this.requestMemo.delete(eKey);\n\n const useRedis =\n !useLocal &&\n gateRedis(this.state);\n\n if (useRedis) {\n try {\n await withAbortSignal(\n \"incremental.set\",\n this.state.opts.abortTimeoutMs,\n async () => {\n const client = await this.state.conn.getOrConnect();\n if (!client) {\n if (this.state.opts.fallback !== \"never\") {\n this.state.memEntries.set(eKey, serialized, ttl);\n }\n return;\n }\n // Compress only the Redis-bound copy; memory stays plain.\n await client.set(\n eKey,\n await compressValue(\n serialized,\n this.state.opts.rest.compression\n ),\n { EX: ttl }\n );\n }\n );\n this.state.emit({ type: \"cache.set\", meta: { backend: \"redis\" } });\n return;\n } catch (err) {\n if (err instanceof CacheTimeoutError) {\n this.state.emit({ type: \"redis.timeout\", meta: { op: \"incremental.set\" } });\n }\n // Fall through to memory.\n }\n }\n\n if (useLocal || this.state.opts.fallback !== \"never\") {\n this.state.memEntries.set(eKey, serialized, ttl);\n this.state.emit({ type: \"cache.set\", meta: { backend: \"memory\" } });\n } else {\n this.state.emit({\n type: \"cache.set.failed\",\n meta: { reason: \"no-fallback\" },\n });\n }\n } catch (err) {\n this.state.logger.error(\"set() error\", {\n message: (err as Error).message,\n });\n this.state.emit({ type: \"cache.set.failed\" });\n }\n }\n\n async revalidateTag(\n tags: string | string[],\n durations?: { expire?: number }\n ): Promise<void> {\n const list = normalizeTags([tags].flat());\n if (list.length === 0) return;\n\n const useLocal = shouldUseLocalIncrementalStore(list);\n const useRedis = !useLocal && gateRedis(this.state);\n\n const now = Date.now();\n const payload: TagState = durations\n ? {\n stale: now,\n ...(durations.expire !== undefined\n ? { expired: now + durations.expire * 1000 }\n : {}),\n }\n : { expired: now };\n\n // Local first.\n for (const t of list) this.state.memTagStates.set(t, payload);\n\n if (!useRedis) {\n this.state.emit({\n type: payload.expired ? \"tag.invalidate.hard\" : \"tag.invalidate.soft\",\n meta: { count: list.length, backend: \"memory\" },\n });\n return;\n }\n\n try {\n await withAbortSignal(\n \"incremental.revalidateTag\",\n this.state.opts.abortTimeoutMs,\n async () => {\n const client = await this.state.conn.getOrConnect();\n if (!client) return;\n await Promise.all(\n list.map((t) =>\n client.set(tagMetaKey(this.state, t), JSON.stringify(payload), {\n EX: ONE_YEAR_SEC,\n })\n )\n );\n }\n );\n this.state.emit({\n type: payload.expired ? \"tag.invalidate.hard\" : \"tag.invalidate.soft\",\n meta: { count: list.length, backend: \"redis\" },\n });\n } catch (err) {\n this.state.logger.warn(\"revalidateTag() failed\", {\n message: (err as Error).message,\n });\n // Hard expirations should propagate so callers know to retry.\n if (payload.expired !== undefined) throw err;\n }\n }\n\n resetRequestCache(): void {\n this.requestMemo.clear();\n }\n}\n\n/**\n * Factory returning a class compatible with Next.js's `cacheHandler` (singular)\n * option. Next.js does `new CacheHandler(ctx)` at request time, so we close\n * over the configured state and produce a class with the spec-required\n * methods. Note: Next constructs the class with just `(ctx)`, so the returned\n * class's constructor signature accepts the single-arg shape.\n */\nexport interface NextCacheHandlerCtor {\n new (ctx?: { revalidatedTags?: string[] }): IncrementalRedisCacheHandler;\n}\n\nexport function createIncrementalCacheHandler(\n opts: CacheHandlerOptions\n): NextCacheHandlerCtor {\n const state = init(opts);\n\n class BoundIncrementalCacheHandler extends IncrementalRedisCacheHandler {\n constructor(ctx?: { revalidatedTags?: string[] }) {\n super(state, ctx);\n }\n }\n\n return BoundIncrementalCacheHandler;\n}\n","/**\n * JSON serialization with Buffer / Map support for ISR cache records.\n *\n * Next.js's IncrementalCacheValue can contain Buffer (rendered HTML body) and\n * Map instances (RSC payload metadata). Plain JSON.stringify destroys both.\n *\n * The `__type` discriminator approach is borrowed from the reference handler\n * in next-redis-cache-demo. The reviver also accepts the legacy\n * `{ type: \"Buffer\", data: number[] }` shape that Node.js's default\n * Buffer.toJSON produces.\n */\n\ninterface BufferEnvelope {\n __type: \"Buffer\";\n data: string;\n}\ninterface MapEnvelope {\n __type: \"Map\";\n entries: Array<[unknown, unknown]>;\n}\ntype Envelope = BufferEnvelope | MapEnvelope;\n\nfunction isEnvelope(value: unknown): value is Envelope {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"__type\" in value &&\n typeof (value as { __type: unknown }).__type === \"string\"\n );\n}\n\ninterface LegacyBufferShape {\n type: \"Buffer\";\n data: number[];\n}\n\nfunction isLegacyBufferShape(value: unknown): value is LegacyBufferShape {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { type?: unknown }).type === \"Buffer\" &&\n Array.isArray((value as { data?: unknown }).data)\n );\n}\n\nfunction replacer(_key: string, value: unknown): unknown {\n if (Buffer.isBuffer(value)) {\n const env: BufferEnvelope = {\n __type: \"Buffer\",\n data: value.toString(\"base64\"),\n };\n return env;\n }\n if (value instanceof Map) {\n const env: MapEnvelope = {\n __type: \"Map\",\n entries: Array.from(value.entries()) as Array<[unknown, unknown]>,\n };\n return env;\n }\n return value;\n}\n\nfunction reviver(_key: string, value: unknown): unknown {\n if (isLegacyBufferShape(value)) {\n return Buffer.from(value.data);\n }\n if (!isEnvelope(value)) return value;\n if (value.__type === \"Buffer\") {\n return Buffer.from((value as BufferEnvelope).data, \"base64\");\n }\n if (value.__type === \"Map\") {\n return new Map((value as MapEnvelope).entries);\n }\n return value;\n}\n\nexport function serializeCacheRecord(record: unknown): string {\n return JSON.stringify(record, replacer);\n}\n\nexport function deserializeCacheRecord<T = unknown>(serialized: string): T | null {\n try {\n return JSON.parse(serialized, reviver) as T;\n } catch {\n return null;\n }\n}\n"]}