@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/CHANGELOG.md +21 -0
- package/dist/cache-components/index.cjs +19 -12
- package/dist/cache-components/index.cjs.map +1 -1
- package/dist/cache-components/index.js +19 -12
- package/dist/cache-components/index.js.map +1 -1
- package/dist/incremental/index.cjs +33 -2
- package/dist/incremental/index.cjs.map +1 -1
- package/dist/incremental/index.d.cts +3 -0
- package/dist/incremental/index.d.ts +3 -0
- package/dist/incremental/index.js +33 -2
- package/dist/incremental/index.js.map +1 -1
- package/dist/index.cjs +52 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +52 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -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/incremental/index.ts","../../src/incremental/handler.ts","../../src/shared/abort.ts","../../src/shared/compress.ts","../../src/shared/client/index.ts","../../src/shared/logger.ts","../../src/shared/memory-fallback.ts","../../src/shared/metrics.ts","../../src/shared/namespace.ts","../../src/shared/build-phase.ts","../../src/incremental/serialize.ts"],"names":["path","adaptRedisV5","createRedisV5Client","adaptIoredis","createIoredisClient","adaptCluster","createIoredisCluster","createIoredisSentinel"],"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 * `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 * 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 * 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 * 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/incremental/index.ts","../../src/incremental/handler.ts","../../src/shared/abort.ts","../../src/shared/compress.ts","../../src/shared/client/index.ts","../../src/shared/logger.ts","../../src/shared/memory-fallback.ts","../../src/shared/metrics.ts","../../src/shared/namespace.ts","../../src/shared/build-phase.ts","../../src/incremental/serialize.ts"],"names":["path","adaptRedisV5","createRedisV5Client","adaptIoredis","createIoredisClient","adaptCluster","createIoredisCluster","createIoredisSentinel"],"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 * `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 * 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 * 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 * 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"]}
|
package/dist/index.cjs
CHANGED
|
@@ -989,47 +989,54 @@ async function getImpl(state, cacheKey, softTags) {
|
|
|
989
989
|
});
|
|
990
990
|
return void 0;
|
|
991
991
|
}
|
|
992
|
-
|
|
992
|
+
const freshnessTags = softTags.length > 0 ? [...softTags, ...envelope.tags] : envelope.tags;
|
|
993
|
+
let tagStale = false;
|
|
994
|
+
if (freshnessTags.length > 0) {
|
|
993
995
|
let mostRecent = 0;
|
|
994
|
-
for (const t of
|
|
996
|
+
for (const t of freshnessTags) {
|
|
995
997
|
const ts = state.localTagTimestamps.get(t);
|
|
996
998
|
if (ts !== void 0 && ts > mostRecent) mostRecent = ts;
|
|
997
999
|
}
|
|
998
1000
|
if (mostRecent > envelope.timestamp) {
|
|
999
|
-
state.
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1001
|
+
if (state.opts.staleWhileRevalidate && partition.freshness !== "expired") {
|
|
1002
|
+
tagStale = true;
|
|
1003
|
+
} else {
|
|
1004
|
+
state.emit({ type: "cache.miss", meta: { reason: "tag-invalidated" } });
|
|
1005
|
+
return void 0;
|
|
1006
|
+
}
|
|
1004
1007
|
}
|
|
1005
1008
|
}
|
|
1006
|
-
|
|
1009
|
+
const freshness = tagStale ? "stale" : partition.freshness;
|
|
1010
|
+
if (freshness === "stale") {
|
|
1011
|
+
const staleMeta = tagStale ? { freshness, reason: "tag-invalidated" } : { freshness };
|
|
1007
1012
|
if (state.opts.singleFlight) {
|
|
1008
1013
|
const isLeader = await tryAcquireRefreshLock(state, cacheKey);
|
|
1009
1014
|
state.emit({
|
|
1010
1015
|
type: isLeader ? "cache.stale.refresh.leader" : "cache.stale.refresh.follower",
|
|
1011
1016
|
ms: Date.now() - start,
|
|
1012
|
-
meta:
|
|
1017
|
+
meta: staleMeta
|
|
1013
1018
|
});
|
|
1014
1019
|
} else {
|
|
1015
1020
|
state.emit({
|
|
1016
1021
|
type: "cache.stale",
|
|
1017
1022
|
ms: Date.now() - start,
|
|
1018
|
-
meta:
|
|
1023
|
+
meta: staleMeta
|
|
1019
1024
|
});
|
|
1020
1025
|
}
|
|
1021
1026
|
} else {
|
|
1022
1027
|
state.emit({
|
|
1023
1028
|
type: "cache.hit",
|
|
1024
1029
|
ms: Date.now() - start,
|
|
1025
|
-
meta: { freshness
|
|
1030
|
+
meta: { freshness }
|
|
1026
1031
|
});
|
|
1027
1032
|
}
|
|
1033
|
+
const revalidateMs = Math.max(0, envelope.revalidate) * 1e3;
|
|
1034
|
+
const outTimestamp = tagStale ? Math.min(envelope.timestamp, Date.now() - revalidateMs - 1) : envelope.timestamp;
|
|
1028
1035
|
return {
|
|
1029
1036
|
value: bufferToStream(Buffer.from(envelope.value, "base64")),
|
|
1030
1037
|
tags: envelope.tags,
|
|
1031
1038
|
stale: envelope.stale,
|
|
1032
|
-
timestamp:
|
|
1039
|
+
timestamp: outTimestamp,
|
|
1033
1040
|
expire: envelope.expire,
|
|
1034
1041
|
revalidate: envelope.revalidate
|
|
1035
1042
|
};
|
|
@@ -1567,8 +1574,35 @@ var IncrementalRedisCacheHandler = class {
|
|
|
1567
1574
|
this.state.emit({ type: "cache.miss", meta: { reason: "tag-state-expired" } });
|
|
1568
1575
|
return null;
|
|
1569
1576
|
}
|
|
1577
|
+
let lastModified = parsed.lastModified;
|
|
1578
|
+
if (!isFetch && typeof lastModified === "number") {
|
|
1579
|
+
const softTs = Math.max(
|
|
1580
|
+
0,
|
|
1581
|
+
...tagStates.map(
|
|
1582
|
+
(s) => s && typeof s.stale === "number" ? s.stale : 0
|
|
1583
|
+
)
|
|
1584
|
+
);
|
|
1585
|
+
if (softTs >= lastModified) {
|
|
1586
|
+
const rev = parsed.revalidateSec;
|
|
1587
|
+
if (typeof rev !== "number" || rev <= 0 || rev >= ONE_YEAR_SEC2) {
|
|
1588
|
+
this.state.emit({
|
|
1589
|
+
type: "cache.miss",
|
|
1590
|
+
meta: { reason: "tag-invalidated" }
|
|
1591
|
+
});
|
|
1592
|
+
return null;
|
|
1593
|
+
}
|
|
1594
|
+
lastModified = Math.min(
|
|
1595
|
+
lastModified,
|
|
1596
|
+
Date.now() - (rev + 1) * 1e3
|
|
1597
|
+
);
|
|
1598
|
+
this.state.emit({
|
|
1599
|
+
type: "cache.stale",
|
|
1600
|
+
meta: { reason: "tag-invalidated" }
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1570
1604
|
this.state.emit({ type: "cache.hit" });
|
|
1571
|
-
return { ...parsed, tags };
|
|
1605
|
+
return { ...parsed, lastModified, tags };
|
|
1572
1606
|
} catch (err) {
|
|
1573
1607
|
this.state.logger.error("get() unexpected error", {
|
|
1574
1608
|
message: err.message
|
|
@@ -1582,7 +1616,11 @@ var IncrementalRedisCacheHandler = class {
|
|
|
1582
1616
|
const tags = extractTagsFromValue(data, ctx);
|
|
1583
1617
|
const useLocal = shouldUseLocalIncrementalStore(tags);
|
|
1584
1618
|
const ttl = normalizeTtlSeconds(data, ctx);
|
|
1585
|
-
const record = {
|
|
1619
|
+
const record = {
|
|
1620
|
+
lastModified: Date.now(),
|
|
1621
|
+
value: data,
|
|
1622
|
+
revalidateSec: ttl
|
|
1623
|
+
};
|
|
1586
1624
|
const serialized = serializeCacheRecord(record);
|
|
1587
1625
|
const eKey = entryKey2(this.state, cacheKey);
|
|
1588
1626
|
this.requestMemo.delete(eKey);
|