@leejpsd/nextjs-cache-handler 1.0.1 → 1.0.2

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#17](https://github.com/leejpsd/nextjs-cache-handler/pull/17) [`44a0889`](https://github.com/leejpsd/nextjs-cache-handler/commit/44a08896d2b364f8da101e8ed0e52d014126bbd9) Thanks [@jeroendegloire](https://github.com/jeroendegloire)! - Fix incremental `isTagStateExpired` so a future `expired` from `revalidateTag(tag, 'max')` no longer hard-misses every tagged entry for a year (#14). Hard invalidations (`updateTag`, single-argument `revalidateTag`) still apply the moment they are read, even on an instance whose clock is behind the one that wrote them.
8
+
9
+ - [#21](https://github.com/leejpsd/nextjs-cache-handler/pull/21) [`3a57a0b`](https://github.com/leejpsd/nextjs-cache-handler/commit/3a57a0bad264e68c70387dbfa241155d4124b4f7) Thanks [@leejpsd](https://github.com/leejpsd)! - Fix seeding of the root route on Next.js versions before 16.3.8. Those versions store and look up prerendered routes under Next's normalized page path, where `/` is `/index`, but the seed wrote the root route under `/`, so it was never read and the first request to the home page after a deploy was a `MISS`. Routes whose path starts with `/index` were also read from the wrong build files. The seed now uses the same normalization as Next for both the artifact path and the key.
10
+
11
+ - [#21](https://github.com/leejpsd/nextjs-cache-handler/pull/21) [`3a57a0b`](https://github.com/leejpsd/nextjs-cache-handler/commit/3a57a0bad264e68c70387dbfa241155d4124b4f7) Thanks [@leejpsd](https://github.com/leejpsd)! - `seedBuildOutput` and the `seed` CLI now write prerendered App Router and Pages Router routes under the route-scoped key that Next.js 16.3.8+ records in each build artifact (`routeCache.key` in `.meta`). From 16.3.8 the runtime never asks a custom cache handler for a bare pathname, so pathname-keyed seeds were written but never read and the first request after a deploy was still a `MISS` (#16). Builds from older Next.js versions carry no such metadata and are seeded under the page path as before; no option or flag is needed.
12
+
3
13
  ## 1.0.1
4
14
 
5
15
  ### Patch Changes
@@ -410,7 +410,9 @@ function clampTtl(revalidate) {
410
410
  return MIN_TTL_SEC;
411
411
  }
412
412
  function routeToFileBase(route) {
413
- return route === "/" ? "/index" : route;
413
+ if (route === "/") return "/index";
414
+ if (/^\/index(\/|$)/.test(route)) return `/index${route}`;
415
+ return route;
414
416
  }
415
417
  function readMeta(file) {
416
418
  try {
@@ -419,6 +421,10 @@ function readMeta(file) {
419
421
  return null;
420
422
  }
421
423
  }
424
+ function resolveRouteKey(base, meta) {
425
+ const key = meta?.routeCache?.key;
426
+ return typeof key === "string" && key.length > 0 ? key : base;
427
+ }
422
428
  async function writeRecord(client, key, value, revalidateSec, opts) {
423
429
  const record = {
424
430
  lastModified: Date.now(),
@@ -470,6 +476,7 @@ async function seedBuildOutput(options) {
470
476
  if (isPages) {
471
477
  const html = path3__default.default.join(dir, "server", "pages", `${base.slice(1)}.html`);
472
478
  const data = path3__default.default.join(dir, "server", "pages", `${base.slice(1)}.json`);
479
+ const pagesMeta = path3__default.default.join(dir, "server", "pages", `${base.slice(1)}.meta`);
473
480
  if (!fs__default.default.existsSync(html)) {
474
481
  summary.skippedIncomplete += 1;
475
482
  continue;
@@ -481,7 +488,8 @@ async function seedBuildOutput(options) {
481
488
  headers: void 0,
482
489
  status: void 0
483
490
  };
484
- const r2 = await writeRecord(client, route, value2, info.initialRevalidateSeconds, writeOpts);
491
+ const key2 = resolveRouteKey(base, readMeta(pagesMeta));
492
+ const r2 = await writeRecord(client, key2, value2, info.initialRevalidateSeconds, writeOpts);
485
493
  if (r2 === "written") summary.pages += 1;
486
494
  else summary.skippedExisting += 1;
487
495
  continue;
@@ -525,7 +533,8 @@ async function seedBuildOutput(options) {
525
533
  status: meta.status
526
534
  };
527
535
  if (segmentData) value.segmentData = segmentData;
528
- const r = await writeRecord(client, route, value, info.initialRevalidateSeconds, writeOpts);
536
+ const key = resolveRouteKey(base, meta);
537
+ const r = await writeRecord(client, key, value, info.initialRevalidateSeconds, writeOpts);
529
538
  if (r === "written") summary.routes += 1;
530
539
  else summary.skippedExisting += 1;
531
540
  } catch (err) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../node_modules/tsup/assets/cjs_shims.js","../../src/shared/node-require.ts","../../src/shared/client/adapter-redis.ts","../../src/shared/client/adapter-ioredis.ts","../../src/cli/index.ts","../../src/shared/client/index.ts","../../src/seed/index.ts","../../src/shared/compress.ts","../../src/shared/namespace.ts","../../src/incremental/serialize.ts"],"names":["createRequire","path","adaptRedisV5","createRedisV5Client","adaptIoredis","createIoredisClient","adaptCluster","createIoredisCluster","createIoredisSentinel","promisify","gzip","gunzip","brotliCompress","brotliDecompress","constants","fs","value","r"],"mappings":"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","file":"index.cjs","sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\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 const like = client as unknown as RedisClientLike;\n like.dispose = () => {\n try {\n client.destroy();\n } catch {\n /* already closed */\n }\n };\n // redis@5 exposes publish natively; subscribe needs a duplicate connection.\n like.subscribe = async (channel, onMessage, onDown) => {\n const sub = client.duplicate();\n const teardown = () => {\n try {\n sub.destroy();\n } catch {\n /* already closed */\n }\n };\n let down = false;\n const markDown = () => {\n if (down) return;\n down = true;\n teardown();\n onDown?.();\n };\n sub.on(\"error\", markDown);\n // reconnectStrategy is false on duplicates — a dropped socket is final,\n // so surface it instead of latching a dead subscription as active.\n sub.on(\"end\", markDown);\n try {\n await sub.connect();\n await sub.subscribe(channel, (message: string) => onMessage(message));\n } catch (err) {\n // CRITICAL: without this, every failed SUBSCRIBE (e.g. ACL without\n // channel permissions) leaks one connected duplicate per retry.\n teardown();\n throw err;\n }\n return async () => teardown();\n };\n return like;\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 const args: (string | number)[] = [];\n if (opts?.EX !== undefined) args.push(\"EX\", opts.EX);\n if (opts?.NX) args.push(\"NX\");\n return (client.set as (...a: unknown[]) => Promise<unknown>)(k, v, ...args);\n },\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 publish: (channel, message) => client.publish(channel, message),\n ...(isClusterClient\n ? {}\n : {\n subscribe: async (\n channel: string,\n onMessage: (message: string) => void,\n onDown?: () => void\n ) => {\n const sub = (client as Redis).duplicate();\n let down = false;\n const markDown = () => {\n if (down) return;\n down = true;\n try {\n sub.disconnect();\n } catch {\n /* already closed */\n }\n onDown?.();\n };\n sub.on(\"error\", markDown);\n sub.on(\"end\", markDown);\n try {\n if (sub.status !== \"ready\" && sub.status !== \"connecting\") {\n await sub.connect();\n }\n await sub.subscribe(channel);\n } catch (err) {\n markDown();\n throw err;\n }\n sub.on(\"message\", (ch: string, message: string) => {\n if (ch === channel) onMessage(message);\n });\n return async () => {\n down = true;\n sub.disconnect();\n };\n },\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 * `nextjs-cache-handler` CLI — agent-friendly project setup & diagnostics.\n *\n * Commands:\n * init [--yes] [--dry-run] [--skills] wire the handlers into a Next.js app\n * doctor [--url <redis-url>] connectivity + cache-state diagnostics\n *\n * Design constraints:\n * - Zero dependencies: node builtins only. Redis access reuses the\n * package's own client adapters (which lazy-load the host app's\n * installed `redis`/`ioredis` peer).\n * - Never destructive by default: existing files are left alone unless\n * `--yes` is passed; next.config changes are shown as instructions.\n * - Output is written for BOTH humans and agents: stable `[ok]/[warn]/\n * [action]` prefixes that are trivial to parse.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { buildClient } from \"../shared/client/index.js\";\nimport { seedBuildOutput } from \"../seed/index.js\";\nimport type { RedisClientLike } from \"../types.js\";\n\nconst OK = \"[ok]\";\nconst WARN = \"[warn]\";\nconst ACTION = \"[action]\";\nconst ERR = \"[error]\";\n\ninterface Ctx {\n cwd: string;\n args: string[];\n flags: Set<string>;\n log: (line: string) => void;\n}\n\n// ─── helpers ─────────────────────────────────────────────────────────────────\n\nfunction readJson(file: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\")) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction detectNextMajor(pkg: Record<string, unknown>): {\n raw: string | null;\n major: number | null;\n supportsCacheComponents: boolean;\n} {\n const deps = {\n ...(pkg.dependencies as Record<string, string> | undefined),\n ...(pkg.devDependencies as Record<string, string> | undefined),\n };\n const raw = deps[\"next\"] ?? null;\n if (!raw) return { raw: null, major: null, supportsCacheComponents: false };\n const m = raw.match(/(\\d+)\\.(\\d+)/);\n if (!m) return { raw, major: null, supportsCacheComponents: false };\n const major = Number(m[1]);\n const minor = Number(m[2]);\n // cacheHandlers exists from 16.1.5; treat 16.1+ ranges as capable and let\n // the peer range enforce the floor precisely.\n const supportsCacheComponents = major > 16 ? false : major === 16 && minor >= 1;\n return { raw, major, supportsCacheComponents };\n}\n\nfunction detectClient(pkg: Record<string, unknown>): \"redis\" | \"ioredis\" | null {\n const deps = {\n ...(pkg.dependencies as Record<string, string> | undefined),\n ...(pkg.devDependencies as Record<string, string> | undefined),\n };\n if (deps[\"redis\"]) return \"redis\";\n if (deps[\"ioredis\"]) return \"ioredis\";\n return null;\n}\n\nfunction findNextConfig(cwd: string): string | null {\n for (const name of [\"next.config.ts\", \"next.config.js\", \"next.config.mjs\", \"next.config.cjs\"]) {\n const p = path.join(cwd, name);\n if (fs.existsSync(p)) return p;\n }\n return null;\n}\n\nconst RULES_BEGIN = \"<!-- nextjs-cache-handler:rules:begin -->\";\nconst RULES_END = \"<!-- nextjs-cache-handler:rules:end -->\";\n\nfunction packagedFile(rel: string): string | null {\n // dist/cli/index.cjs|js → package root is two levels up.\n const root = path.resolve(__dirname, \"..\", \"..\");\n const p = path.join(root, rel);\n return fs.existsSync(p) ? p : null;\n}\n\nfunction shimSource(kind: \"incremental\" | \"cache-components\", clientType: string): string {\n const factory =\n kind === \"incremental\"\n ? \"createIncrementalCacheHandler\"\n : \"createCacheComponentsHandler\";\n const subpath = kind === \"incremental\" ? \"incremental\" : \"cache-components\";\n return `// Generated by \\`npx nextjs-cache-handler init\\`\nconst { ${factory} } = require(\"@leejpsd/nextjs-cache-handler/${subpath}\");\n\nmodule.exports = ${factory}({\n client: { type: \"${clientType}\", url: process.env.REDIS_URL },\n // Per-deploy namespace isolation — set DEPLOYMENT_VERSION in every runtime\n // environment (Docker: the runner stage), e.g. the git SHA.\n buildNamespace: () => process.env.DEPLOYMENT_VERSION,\n});\n`;\n}\n\n// ─── init ────────────────────────────────────────────────────────────────────\n\nexport async function init(ctx: Ctx): Promise<number> {\n const { cwd, flags, log } = ctx;\n const apply = flags.has(\"--yes\") && !flags.has(\"--dry-run\");\n\n const pkg = readJson(path.join(cwd, \"package.json\"));\n if (!pkg) {\n log(`${ERR} no package.json in ${cwd} — run inside your Next.js project`);\n return 1;\n }\n\n const next = detectNextMajor(pkg);\n if (!next.raw) {\n log(`${ERR} \"next\" is not a dependency here — not a Next.js project`);\n return 1;\n }\n if (next.major !== null && next.major < 15) {\n log(`${ERR} next@${next.raw} unsupported — this package needs next >=15.0.0 <17`);\n return 1;\n }\n log(`${OK} next: ${next.raw} → ${next.supportsCacheComponents ? \"BOTH handlers (ISR + 'use cache')\" : \"ISR handler only\"}`);\n\n const deps = pkg.dependencies as Record<string, string> | undefined;\n if (!deps?.[\"@leejpsd/nextjs-cache-handler\"]) {\n log(`${ACTION} install the package first: npm i @leejpsd/nextjs-cache-handler`);\n } else {\n log(`${OK} @leejpsd/nextjs-cache-handler ${deps[\"@leejpsd/nextjs-cache-handler\"]}`);\n }\n\n const client = detectClient(pkg);\n if (!client) {\n log(`${ACTION} no Redis client installed — run: npm i redis (or ioredis for Cluster/Sentinel)`);\n } else {\n log(`${OK} redis client: ${client}`);\n }\n const clientType = client ?? \"redis\";\n\n // 1) Wrapper shims.\n const wanted: Array<[\"incremental\" | \"cache-components\", string]> = [\n [\"incremental\", \"cache-incremental.cjs\"],\n ];\n if (next.supportsCacheComponents) wanted.push([\"cache-components\", \"cache-components.cjs\"]);\n\n for (const [kind, file] of wanted) {\n const target = path.join(cwd, file);\n if (fs.existsSync(target)) {\n log(`${OK} ${file} already exists — leaving it untouched`);\n continue;\n }\n if (apply) {\n fs.writeFileSync(target, shimSource(kind, clientType));\n log(`${OK} wrote ${file}`);\n } else {\n log(`${ACTION} would create ${file} (re-run with --yes to write)`);\n }\n }\n\n // 2) next.config guidance (never auto-edited — users customize this file).\n const cfg = findNextConfig(cwd);\n const cfgLines = [\n `cacheHandler: require.resolve(\"./cache-incremental.cjs\"),`,\n ...(next.supportsCacheComponents\n ? [\n `cacheHandlers: { default: require.resolve(\"./cache-components.cjs\") },`,\n `cacheComponents: true,`,\n ]\n : []),\n `cacheMaxMemorySize: 0, // required for multi-instance correctness`,\n ];\n if (!cfg) {\n log(`${WARN} no next.config found — create one with:`);\n } else {\n const body = fs.readFileSync(cfg, \"utf8\");\n if (body.includes(\"cacheHandler\")) {\n log(`${OK} ${path.basename(cfg)} already references a cacheHandler — verify it points at the shims above`);\n } else {\n log(`${ACTION} add to ${path.basename(cfg)}:`);\n }\n if (cfg.endsWith(\".mjs\")) {\n log(`${WARN} ESM config: add import { createRequire } from \"module\"; const require = createRequire(import.meta.url);`);\n }\n }\n for (const l of cfgLines) log(` ${l}`);\n\n // 3) Env template.\n const envExample = path.join(cwd, \".env.example\");\n const envBlock = `\\n# @leejpsd/nextjs-cache-handler\\nREDIS_URL=redis://127.0.0.1:6379\\nDEPLOYMENT_VERSION=dev\\n`;\n if (fs.existsSync(envExample)) {\n const body = fs.readFileSync(envExample, \"utf8\");\n if (body.includes(\"REDIS_URL\")) {\n log(`${OK} .env.example already mentions REDIS_URL`);\n } else if (apply) {\n fs.appendFileSync(envExample, envBlock);\n log(`${OK} appended REDIS_URL / DEPLOYMENT_VERSION to .env.example`);\n } else {\n log(`${ACTION} would append REDIS_URL / DEPLOYMENT_VERSION to .env.example`);\n }\n } else {\n log(`${ACTION} set REDIS_URL and DEPLOYMENT_VERSION in every runtime environment`);\n }\n\n // 4) Agent rules injection (idempotent via markers).\n const rulesSrc = packagedFile(\"rules/nextjs-cache-rules.md\");\n const ruleTargets = [\"CLAUDE.md\", \"AGENTS.md\"]\n .map((f) => path.join(cwd, f))\n .filter((p) => fs.existsSync(p));\n if (rulesSrc && ruleTargets.length > 0) {\n const rules = `\\n${RULES_BEGIN}\\n${fs.readFileSync(rulesSrc, \"utf8\")}\\n${RULES_END}\\n`;\n for (const target of ruleTargets) {\n const body = fs.readFileSync(target, \"utf8\");\n if (body.includes(RULES_BEGIN)) {\n log(`${OK} ${path.basename(target)} already has the cache rules block`);\n } else if (apply) {\n fs.appendFileSync(target, rules);\n log(`${OK} appended cache rules to ${path.basename(target)}`);\n } else {\n log(`${ACTION} would append cache rules to ${path.basename(target)}`);\n }\n }\n } else if (ruleTargets.length === 0) {\n log(`${WARN} no CLAUDE.md/AGENTS.md found — skip rules injection (create one to guide your agent)`);\n }\n\n // 5) MCP registration — one file turns any MCP-capable agent (Claude\n // Code, Cursor, ...) into a cache operator via npx (no install needed).\n const mcpPath = path.join(cwd, \".mcp.json\");\n if (fs.existsSync(mcpPath)) {\n const body = fs.readFileSync(mcpPath, \"utf8\");\n if (body.includes(\"nextjs-cache-handler-mcp\")) {\n log(`${OK} .mcp.json already registers the cache MCP server`);\n } else {\n log(`${ACTION} .mcp.json exists — add the \"nextjs-cache\" server manually (see @leejpsd/nextjs-cache-handler-mcp README)`);\n }\n } else if (apply) {\n fs.writeFileSync(\n mcpPath,\n JSON.stringify(\n {\n mcpServers: {\n \"nextjs-cache\": {\n command: \"npx\",\n args: [\"-y\", \"@leejpsd/nextjs-cache-handler-mcp\"],\n env: {\n REDIS_URL: \"redis://127.0.0.1:6379\",\n DEPLOYMENT_VERSION: \"dev\",\n },\n },\n },\n },\n null,\n 2\n ) + \"\\n\"\n );\n log(`${OK} wrote .mcp.json — your agent now has cache_health/tag_state/... tools (edit REDIS_URL for real environments)`);\n } else {\n log(`${ACTION} would create .mcp.json registering @leejpsd/nextjs-cache-handler-mcp`);\n }\n\n // 6) Optional skill install.\n if (flags.has(\"--skills\")) {\n const skillSrc = packagedFile(\"skills/nextjs-redis-cache/SKILL.md\");\n if (skillSrc) {\n const dest = path.join(cwd, \".claude\", \"skills\", \"nextjs-redis-cache\", \"SKILL.md\");\n if (apply) {\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.copyFileSync(skillSrc, dest);\n log(`${OK} installed skill to .claude/skills/nextjs-redis-cache/`);\n } else {\n log(`${ACTION} would install skill to .claude/skills/nextjs-redis-cache/`);\n }\n }\n }\n\n log(`${OK} init ${apply ? \"complete\" : \"preview complete — re-run with --yes to apply\"}. Verify with: npx nextjs-cache-handler doctor`);\n return 0;\n}\n\n// ─── doctor ──────────────────────────────────────────────────────────────────\n\nexport async function doctor(ctx: Ctx): Promise<number> {\n const { args, log } = ctx;\n const urlIdx = args.indexOf(\"--url\");\n const url = urlIdx >= 0 ? args[urlIdx + 1] : process.env.REDIS_URL;\n if (!url) {\n log(`${ERR} no Redis URL — pass --url <redis-url> or set REDIS_URL`);\n return 1;\n }\n\n const deployment = process.env.DEPLOYMENT_VERSION;\n log(deployment ? `${OK} DEPLOYMENT_VERSION=${deployment}` : `${WARN} DEPLOYMENT_VERSION not set — keys will use the \"unversioned\" namespace`);\n\n let client: RedisClientLike;\n try {\n // Prefer node-redis; fall back to ioredis when only that peer is installed.\n try {\n client = await buildClient({ type: \"redis\", url });\n } catch (err) {\n if (/Cannot find module/.test((err as Error).message)) {\n client = await buildClient({ type: \"ioredis\", url });\n } else {\n throw err;\n }\n }\n if (!client.isOpen) await client.connect();\n } catch (err) {\n log(`${ERR} connect failed: ${(err as Error).message}`);\n log(`${ACTION} check the URL/network, or install a client: npm i redis (or ioredis)`);\n return 1;\n }\n\n try {\n const t0 = Date.now();\n await client.ping();\n log(`${OK} redis PING ${Date.now() - t0}ms (${url.replace(/\\/\\/[^@]*@/, \"//***@\")})`);\n\n const counts = new Map<string, number>();\n for await (const chunk of client.scanIterator({ MATCH: \"next-*\", COUNT: 500 })) {\n const keys = Array.isArray(chunk) ? chunk : [chunk];\n for (const k of keys) {\n const key = String(k);\n const m = key.match(/^(next-cache|next-incremental):([a-z-]+):/);\n const bucket = m ? `${m[1]}:${m[2]}` : \"other\";\n counts.set(bucket, (counts.get(bucket) ?? 0) + 1);\n }\n }\n if (counts.size === 0) {\n log(`${WARN} no next-* keys found — cache not yet exercised (or a custom keyPrefix is in use)`);\n } else {\n for (const [bucket, n] of [...counts.entries()].sort()) {\n log(`${OK} ${bucket}* — ${n} keys`);\n }\n }\n\n // Round-trip probe in an isolated namespace.\n const probeKey = `next-cache:doctor:${Date.now()}`;\n await client.set(probeKey, \"ok\", { EX: 30 });\n const back = await client.get(probeKey);\n await client.del(probeKey);\n log(back === \"ok\" ? `${OK} write/read round-trip` : `${ERR} round-trip failed`);\n return back === \"ok\" ? 0 : 1;\n } finally {\n client.dispose?.();\n }\n}\n\n\n// ─── seed ────────────────────────────────────────────────────────────────────\n\nexport async function seed(ctx: Ctx): Promise<number> {\n const { args, flags, log } = ctx;\n const urlIdx = args.indexOf(\"--url\");\n const url = urlIdx >= 0 ? args[urlIdx + 1] : process.env.REDIS_URL;\n if (!url) {\n log(`${ERR} no Redis URL — pass --url <redis-url> or set REDIS_URL`);\n return 1;\n }\n const flagVal = (name: string): string | undefined => {\n const i = args.indexOf(name);\n return i >= 0 ? args[i + 1] : undefined;\n };\n const dir = flagVal(\"--dir\") ?? \".next\";\n const keyPrefix = flagVal(\"--key-prefix\");\n const namespace = flagVal(\"--namespace\");\n const compression = flagVal(\"--compression\") as \"gzip\" | \"brotli\" | undefined;\n const hashTag = flags.has(\"--hash-tag\");\n\n const ns =\n namespace ??\n process.env.DEPLOYMENT_VERSION ??\n process.env.GIT_HASH ??\n \"unversioned\";\n if (ns === \"unversioned\") {\n log(`${WARN} no namespace — seeding into \"unversioned\" (set DEPLOYMENT_VERSION or pass --namespace)`);\n }\n // Print the exact key shape so a config mismatch with the runtime handler\n // (custom keyPrefix / hashTag) is visible instead of silently seeding\n // keys the app never reads.\n log(`${OK} target keys: ${keyPrefix ?? \"next-incremental:\"}entry:${hashTag ? `{${ns}}` : ns}:*`);\n\n const seedOpts = {\n dir,\n buildNamespace: ns,\n ...(keyPrefix ? { keyPrefix } : {}),\n ...(compression ? { compression } : {}),\n ...(hashTag ? { hashTag: true } : {}),\n };\n const report = (summary: Awaited<ReturnType<typeof seedBuildOutput>>): number => {\n log(`${OK} seeded: ${summary.routes} app routes, ${summary.pages} pages routes, ${summary.fetch} fetch entries`);\n if (summary.skippedExisting > 0)\n log(`${OK} left ${summary.skippedExisting} newer live entries untouched (NX)`);\n if (summary.skippedRouteHandlers > 0)\n log(`${OK} ${summary.skippedRouteHandlers} prerendered route handlers not seeded (by design)`);\n if (summary.skippedIncomplete > 0)\n log(`${WARN} skipped ${summary.skippedIncomplete} routes (incomplete files or PPR resume state)`);\n for (const e of summary.errors.slice(0, 5)) log(`${WARN} ${e}`);\n return summary.errors.length > 0 ? 1 : 0;\n };\n\n try {\n return report(\n await seedBuildOutput({ client: { type: \"redis\", url }, ...seedOpts })\n );\n } catch (err) {\n const msg = (err as Error).message;\n if (/Cannot find module 'redis'/.test(msg)) {\n // Retry with ioredis when only that peer is installed.\n try {\n return report(\n await seedBuildOutput({ client: { type: \"ioredis\", url }, ...seedOpts })\n );\n } catch (err2) {\n log(`${ERR} ${(err2 as Error).message}`);\n return 1;\n }\n }\n log(`${ERR} ${msg}`);\n return 1;\n }\n}\n\n// ─── entry ───────────────────────────────────────────────────────────────────\n\nexport async function main(argv: string[] = process.argv.slice(2)): Promise<number> {\n const [cmd, ...rest] = argv;\n const ctx: Ctx = {\n cwd: process.cwd(),\n args: rest,\n flags: new Set(rest.filter((a) => a.startsWith(\"--\"))),\n log: (l) => console.log(l),\n };\n switch (cmd) {\n case \"init\":\n return init(ctx);\n case \"doctor\":\n return doctor(ctx);\n case \"seed\":\n return seed(ctx);\n default:\n console.log(`nextjs-cache-handler <command>\n\nCommands:\n init [--yes] [--dry-run] [--skills] wire handlers into this Next.js app\n doctor [--url <redis-url>] connectivity + cache diagnostics\n seed [--dir .next] [--url <u>] [--namespace <ns>] [--key-prefix <p>] [--hash-tag] [--compression gzip|brotli]\n seed prerendered build output into Redis\n\nAgent setup instructions:\n https://raw.githubusercontent.com/leejpsd/nextjs-cache-handler/main/setup-instructions/setup.md`);\n return cmd ? 1 : 0;\n }\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 * Build-output cache seeding.\n *\n * `next build` prerenders pages and fetch-cache entries into `.next/`, but a\n * fresh deployment's Redis is empty — every first request pays a full\n * regeneration (and N instances pay it N times). `seedBuildOutput()` walks\n * the build output and inserts it into Redis in the exact record format the\n * incremental handler reads, using **NX semantics**: an entry that a running\n * instance has already written (necessarily newer) is never overwritten.\n *\n * Run it once per deploy, after `next build` and before (or while) traffic\n * shifts — e.g. as a Docker entrypoint step or CI job:\n *\n * npx nextjs-cache-handler seed # uses REDIS_URL / DEPLOYMENT_VERSION\n * npx nextjs-cache-handler seed --dir .next\n *\n * Seeds:\n * - App Router routes (`.next/server/app/<route>.{html,rsc,meta}` +\n * PPR `.segments/`) → APP_PAGE records\n * - Pages Router routes (`.next/server/pages/<route>.{html,json}`) → PAGES\n * - fetch cache (`.next/cache/fetch-cache/<hash>`) → FETCH records\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { buildClient } from \"../shared/client/index.js\";\nimport { compressValue } from \"../shared/compress.js\";\nimport { buildKey, resolveBuildNamespace } from \"../shared/namespace.js\";\nimport { serializeCacheRecord } from \"../incremental/serialize.js\";\nimport type {\n Logger,\n RedisClientConfig,\n RedisClientFactory,\n RedisClientLike,\n} from \"../types.js\";\n\nconst ONE_YEAR_SEC = 60 * 60 * 24 * 365;\nconst MIN_TTL_SEC = 60;\nconst DEFAULT_KEY_PREFIX = \"next-incremental:\";\n\nexport interface SeedOptions {\n client: RedisClientFactory | RedisClientConfig;\n /** Path to the build output. Default: `./.next`. */\n dir?: string;\n keyPrefix?: string;\n buildNamespace?: string | (() => string);\n compression?: \"gzip\" | \"brotli\";\n hashTag?: boolean;\n logger?: Pick<Logger, \"warn\">;\n}\n\nexport interface SeedSummary {\n /** App Router routes written. */\n routes: number;\n /** Pages Router routes written. */\n pages: number;\n /** fetch-cache entries written. */\n fetch: number;\n /** Entries skipped because a (newer) live entry already existed (NX). */\n skippedExisting: number;\n /** Routes skipped because their files were incomplete or PPR-postponed. */\n skippedIncomplete: number;\n /** Prerendered route handlers (.body) — never seeded, by design. */\n skippedRouteHandlers: number;\n errors: string[];\n}\n\ninterface ManifestRoute {\n initialRevalidateSeconds?: number | false;\n dataRoute?: string | null;\n srcRoute?: string | null;\n}\n\nfunction clampTtl(revalidate: number | false | undefined): number {\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\nfunction routeToFileBase(route: string): string {\n return route === \"/\" ? \"/index\" : route;\n}\n\nfunction readMeta(file: string): {\n status?: number;\n headers?: Record<string, string>;\n segmentPaths?: string[];\n postponed?: string;\n} | null {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\")) as ReturnType<typeof readMeta>;\n } catch {\n return null;\n }\n}\n\nasync function writeRecord(\n client: RedisClientLike,\n key: string,\n value: unknown,\n revalidateSec: number | false | undefined,\n opts: Required<Pick<SeedOptions, \"keyPrefix\" | \"hashTag\">> & {\n ns: string;\n compression?: \"gzip\" | \"brotli\";\n }\n): Promise<\"written\" | \"skipped\"> {\n const record = {\n lastModified: Date.now(),\n value,\n revalidateSec: clampTtl(revalidateSec),\n };\n const redisKey = buildKey(`${opts.keyPrefix}entry:`, opts.ns, key, opts.hashTag);\n const payload = await compressValue(\n serializeCacheRecord(record),\n opts.compression\n );\n const result = await client.set(redisKey, payload, {\n EX: clampTtl(revalidateSec),\n NX: true,\n });\n // Redis returns null (nil) when NX blocks the write.\n return result === null ? \"skipped\" : \"written\";\n}\n\nexport async function seedBuildOutput(options: SeedOptions): Promise<SeedSummary> {\n const dir = path.resolve(options.dir ?? \".next\");\n const keyPrefix = options.keyPrefix ?? DEFAULT_KEY_PREFIX;\n const hashTag = options.hashTag ?? false;\n const ns = resolveBuildNamespace(options.buildNamespace);\n const warn = options.logger?.warn ?? (() => {});\n const summary: SeedSummary = {\n routes: 0,\n pages: 0,\n fetch: 0,\n skippedExisting: 0,\n skippedIncomplete: 0,\n skippedRouteHandlers: 0,\n errors: [],\n };\n\n const manifestPath = path.join(dir, \"prerender-manifest.json\");\n if (!fs.existsSync(manifestPath)) {\n throw new Error(\n `[next-cache] no prerender-manifest.json in ${dir} — run \\`next build\\` first`\n );\n }\n const manifest = JSON.parse(fs.readFileSync(manifestPath, \"utf8\")) as {\n routes?: Record<string, ManifestRoute>;\n };\n\n const client = await buildClient(options.client);\n if (!client.isOpen) await client.connect();\n\n const writeOpts = { keyPrefix, hashTag, ns, ...(options.compression ? { compression: options.compression } : {}) };\n\n try {\n // ── 1) Prerendered routes ────────────────────────────────────────────────\n for (const [route, info] of Object.entries(manifest.routes ?? {})) {\n try {\n const isPages = typeof info.dataRoute === \"string\" && info.dataRoute.endsWith(\".json\");\n const base = routeToFileBase(route);\n\n if (isPages) {\n const html = path.join(dir, \"server\", \"pages\", `${base.slice(1)}.html`);\n const data = path.join(dir, \"server\", \"pages\", `${base.slice(1)}.json`);\n if (!fs.existsSync(html)) {\n summary.skippedIncomplete += 1;\n continue;\n }\n const value = {\n kind: \"PAGES\",\n html: fs.readFileSync(html, \"utf8\"),\n pageData: fs.existsSync(data)\n ? (JSON.parse(fs.readFileSync(data, \"utf8\")) as unknown)\n : {},\n headers: undefined,\n status: undefined,\n };\n const r = await writeRecord(client, route, value, info.initialRevalidateSeconds, writeOpts);\n if (r === \"written\") summary.pages += 1;\n else summary.skippedExisting += 1;\n continue;\n }\n\n // App Router\n const htmlPath = path.join(dir, \"server\", \"app\", `${base.slice(1)}.html`);\n const rscPath = path.join(dir, \"server\", \"app\", `${base.slice(1)}.rsc`);\n const metaPath = path.join(dir, \"server\", \"app\", `${base.slice(1)}.meta`);\n if (!fs.existsSync(htmlPath) || !fs.existsSync(metaPath)) {\n // Prerendered route handlers emit .body/.meta instead of .html —\n // they are intentionally not seeded, and not \"incomplete\".\n if (fs.existsSync(path.join(dir, \"server\", \"app\", `${base.slice(1)}.body`))) {\n summary.skippedRouteHandlers += 1;\n } else {\n summary.skippedIncomplete += 1;\n }\n continue;\n }\n const meta = readMeta(metaPath) ?? {};\n if (meta.postponed) {\n // PPR routes with resume state cannot be faithfully seeded from\n // static files (the runtime needs `postponed` to resume dynamic\n // holes, and Next intentionally omits the .rsc for them). Serving\n // a seeded copy would freeze the unresolved shell as final HTML.\n summary.skippedIncomplete += 1;\n continue;\n }\n\n let segmentData: Map<string, Buffer> | undefined;\n if (Array.isArray(meta.segmentPaths) && meta.segmentPaths.length > 0) {\n const segDir = path.join(dir, \"server\", \"app\", `${base.slice(1)}.segments`);\n segmentData = new Map();\n for (const segPath of meta.segmentPaths) {\n const segFile = path.join(segDir, `${segPath.slice(1)}.segment.rsc`);\n if (fs.existsSync(segFile)) {\n segmentData.set(segPath, fs.readFileSync(segFile));\n }\n }\n if (segmentData.size !== meta.segmentPaths.length) {\n // Partial segment sets would break PPR resumes — safer to skip.\n summary.skippedIncomplete += 1;\n continue;\n }\n }\n\n const value: Record<string, unknown> = {\n kind: \"APP_PAGE\",\n html: fs.readFileSync(htmlPath, \"utf8\"),\n rscData: fs.existsSync(rscPath) ? fs.readFileSync(rscPath) : undefined,\n headers: meta.headers,\n status: meta.status,\n };\n if (segmentData) value.segmentData = segmentData;\n\n const r = await writeRecord(client, route, value, info.initialRevalidateSeconds, writeOpts);\n if (r === \"written\") summary.routes += 1;\n else summary.skippedExisting += 1;\n } catch (err) {\n summary.errors.push(`${route}: ${(err as Error).message}`);\n warn(\"seed: route failed\", { route, message: (err as Error).message });\n }\n }\n\n // ── 2) fetch cache ───────────────────────────────────────────────────────\n const fetchDir = path.join(dir, \"cache\", \"fetch-cache\");\n if (fs.existsSync(fetchDir)) {\n for (const file of fs.readdirSync(fetchDir)) {\n if (file.startsWith(\".\")) continue;\n try {\n const raw = fs.readFileSync(path.join(fetchDir, file), \"utf8\");\n const value = JSON.parse(raw) as { kind?: string; revalidate?: number };\n if (value.kind !== \"FETCH\") continue;\n const r = await writeRecord(client, file, value, value.revalidate, writeOpts);\n if (r === \"written\") summary.fetch += 1;\n else summary.skippedExisting += 1;\n } catch (err) {\n summary.errors.push(`fetch:${file}: ${(err as Error).message}`);\n }\n }\n }\n } finally {\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 */\n }\n }\n\n return summary;\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 * 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 * 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(this: Record<string, unknown>, key: string, value: unknown): unknown {\n // Buffer.prototype.toJSON runs BEFORE the replacer (JSON spec), so `value`\n // is already { type: \"Buffer\", data: number[] } here. `this[key]` is the\n // pre-toJSON original — the only place the real Buffer is still visible.\n const raw = this[key];\n if (Buffer.isBuffer(raw)) {\n const env: BufferEnvelope = {\n __type: \"Buffer\",\n data: raw.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/cjs_shims.js","../../src/shared/node-require.ts","../../src/shared/client/adapter-redis.ts","../../src/shared/client/adapter-ioredis.ts","../../src/cli/index.ts","../../src/shared/client/index.ts","../../src/seed/index.ts","../../src/shared/compress.ts","../../src/shared/namespace.ts","../../src/incremental/serialize.ts"],"names":["createRequire","path","adaptRedisV5","createRedisV5Client","adaptIoredis","createIoredisClient","adaptCluster","createIoredisCluster","createIoredisSentinel","promisify","gzip","gunzip","brotliCompress","brotliDecompress","constants","fs","value","key","r"],"mappings":"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","file":"index.cjs","sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\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 const like = client as unknown as RedisClientLike;\n like.dispose = () => {\n try {\n client.destroy();\n } catch {\n /* already closed */\n }\n };\n // redis@5 exposes publish natively; subscribe needs a duplicate connection.\n like.subscribe = async (channel, onMessage, onDown) => {\n const sub = client.duplicate();\n const teardown = () => {\n try {\n sub.destroy();\n } catch {\n /* already closed */\n }\n };\n let down = false;\n const markDown = () => {\n if (down) return;\n down = true;\n teardown();\n onDown?.();\n };\n sub.on(\"error\", markDown);\n // reconnectStrategy is false on duplicates — a dropped socket is final,\n // so surface it instead of latching a dead subscription as active.\n sub.on(\"end\", markDown);\n try {\n await sub.connect();\n await sub.subscribe(channel, (message: string) => onMessage(message));\n } catch (err) {\n // CRITICAL: without this, every failed SUBSCRIBE (e.g. ACL without\n // channel permissions) leaks one connected duplicate per retry.\n teardown();\n throw err;\n }\n return async () => teardown();\n };\n return like;\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 const args: (string | number)[] = [];\n if (opts?.EX !== undefined) args.push(\"EX\", opts.EX);\n if (opts?.NX) args.push(\"NX\");\n return (client.set as (...a: unknown[]) => Promise<unknown>)(k, v, ...args);\n },\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 publish: (channel, message) => client.publish(channel, message),\n ...(isClusterClient\n ? {}\n : {\n subscribe: async (\n channel: string,\n onMessage: (message: string) => void,\n onDown?: () => void\n ) => {\n const sub = (client as Redis).duplicate();\n let down = false;\n const markDown = () => {\n if (down) return;\n down = true;\n try {\n sub.disconnect();\n } catch {\n /* already closed */\n }\n onDown?.();\n };\n sub.on(\"error\", markDown);\n sub.on(\"end\", markDown);\n try {\n if (sub.status !== \"ready\" && sub.status !== \"connecting\") {\n await sub.connect();\n }\n await sub.subscribe(channel);\n } catch (err) {\n markDown();\n throw err;\n }\n sub.on(\"message\", (ch: string, message: string) => {\n if (ch === channel) onMessage(message);\n });\n return async () => {\n down = true;\n sub.disconnect();\n };\n },\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 * `nextjs-cache-handler` CLI — agent-friendly project setup & diagnostics.\n *\n * Commands:\n * init [--yes] [--dry-run] [--skills] wire the handlers into a Next.js app\n * doctor [--url <redis-url>] connectivity + cache-state diagnostics\n *\n * Design constraints:\n * - Zero dependencies: node builtins only. Redis access reuses the\n * package's own client adapters (which lazy-load the host app's\n * installed `redis`/`ioredis` peer).\n * - Never destructive by default: existing files are left alone unless\n * `--yes` is passed; next.config changes are shown as instructions.\n * - Output is written for BOTH humans and agents: stable `[ok]/[warn]/\n * [action]` prefixes that are trivial to parse.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { buildClient } from \"../shared/client/index.js\";\nimport { seedBuildOutput } from \"../seed/index.js\";\nimport type { RedisClientLike } from \"../types.js\";\n\nconst OK = \"[ok]\";\nconst WARN = \"[warn]\";\nconst ACTION = \"[action]\";\nconst ERR = \"[error]\";\n\ninterface Ctx {\n cwd: string;\n args: string[];\n flags: Set<string>;\n log: (line: string) => void;\n}\n\n// ─── helpers ─────────────────────────────────────────────────────────────────\n\nfunction readJson(file: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\")) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction detectNextMajor(pkg: Record<string, unknown>): {\n raw: string | null;\n major: number | null;\n supportsCacheComponents: boolean;\n} {\n const deps = {\n ...(pkg.dependencies as Record<string, string> | undefined),\n ...(pkg.devDependencies as Record<string, string> | undefined),\n };\n const raw = deps[\"next\"] ?? null;\n if (!raw) return { raw: null, major: null, supportsCacheComponents: false };\n const m = raw.match(/(\\d+)\\.(\\d+)/);\n if (!m) return { raw, major: null, supportsCacheComponents: false };\n const major = Number(m[1]);\n const minor = Number(m[2]);\n // cacheHandlers exists from 16.1.5; treat 16.1+ ranges as capable and let\n // the peer range enforce the floor precisely.\n const supportsCacheComponents = major > 16 ? false : major === 16 && minor >= 1;\n return { raw, major, supportsCacheComponents };\n}\n\nfunction detectClient(pkg: Record<string, unknown>): \"redis\" | \"ioredis\" | null {\n const deps = {\n ...(pkg.dependencies as Record<string, string> | undefined),\n ...(pkg.devDependencies as Record<string, string> | undefined),\n };\n if (deps[\"redis\"]) return \"redis\";\n if (deps[\"ioredis\"]) return \"ioredis\";\n return null;\n}\n\nfunction findNextConfig(cwd: string): string | null {\n for (const name of [\"next.config.ts\", \"next.config.js\", \"next.config.mjs\", \"next.config.cjs\"]) {\n const p = path.join(cwd, name);\n if (fs.existsSync(p)) return p;\n }\n return null;\n}\n\nconst RULES_BEGIN = \"<!-- nextjs-cache-handler:rules:begin -->\";\nconst RULES_END = \"<!-- nextjs-cache-handler:rules:end -->\";\n\nfunction packagedFile(rel: string): string | null {\n // dist/cli/index.cjs|js → package root is two levels up.\n const root = path.resolve(__dirname, \"..\", \"..\");\n const p = path.join(root, rel);\n return fs.existsSync(p) ? p : null;\n}\n\nfunction shimSource(kind: \"incremental\" | \"cache-components\", clientType: string): string {\n const factory =\n kind === \"incremental\"\n ? \"createIncrementalCacheHandler\"\n : \"createCacheComponentsHandler\";\n const subpath = kind === \"incremental\" ? \"incremental\" : \"cache-components\";\n return `// Generated by \\`npx nextjs-cache-handler init\\`\nconst { ${factory} } = require(\"@leejpsd/nextjs-cache-handler/${subpath}\");\n\nmodule.exports = ${factory}({\n client: { type: \"${clientType}\", url: process.env.REDIS_URL },\n // Per-deploy namespace isolation — set DEPLOYMENT_VERSION in every runtime\n // environment (Docker: the runner stage), e.g. the git SHA.\n buildNamespace: () => process.env.DEPLOYMENT_VERSION,\n});\n`;\n}\n\n// ─── init ────────────────────────────────────────────────────────────────────\n\nexport async function init(ctx: Ctx): Promise<number> {\n const { cwd, flags, log } = ctx;\n const apply = flags.has(\"--yes\") && !flags.has(\"--dry-run\");\n\n const pkg = readJson(path.join(cwd, \"package.json\"));\n if (!pkg) {\n log(`${ERR} no package.json in ${cwd} — run inside your Next.js project`);\n return 1;\n }\n\n const next = detectNextMajor(pkg);\n if (!next.raw) {\n log(`${ERR} \"next\" is not a dependency here — not a Next.js project`);\n return 1;\n }\n if (next.major !== null && next.major < 15) {\n log(`${ERR} next@${next.raw} unsupported — this package needs next >=15.0.0 <17`);\n return 1;\n }\n log(`${OK} next: ${next.raw} → ${next.supportsCacheComponents ? \"BOTH handlers (ISR + 'use cache')\" : \"ISR handler only\"}`);\n\n const deps = pkg.dependencies as Record<string, string> | undefined;\n if (!deps?.[\"@leejpsd/nextjs-cache-handler\"]) {\n log(`${ACTION} install the package first: npm i @leejpsd/nextjs-cache-handler`);\n } else {\n log(`${OK} @leejpsd/nextjs-cache-handler ${deps[\"@leejpsd/nextjs-cache-handler\"]}`);\n }\n\n const client = detectClient(pkg);\n if (!client) {\n log(`${ACTION} no Redis client installed — run: npm i redis (or ioredis for Cluster/Sentinel)`);\n } else {\n log(`${OK} redis client: ${client}`);\n }\n const clientType = client ?? \"redis\";\n\n // 1) Wrapper shims.\n const wanted: Array<[\"incremental\" | \"cache-components\", string]> = [\n [\"incremental\", \"cache-incremental.cjs\"],\n ];\n if (next.supportsCacheComponents) wanted.push([\"cache-components\", \"cache-components.cjs\"]);\n\n for (const [kind, file] of wanted) {\n const target = path.join(cwd, file);\n if (fs.existsSync(target)) {\n log(`${OK} ${file} already exists — leaving it untouched`);\n continue;\n }\n if (apply) {\n fs.writeFileSync(target, shimSource(kind, clientType));\n log(`${OK} wrote ${file}`);\n } else {\n log(`${ACTION} would create ${file} (re-run with --yes to write)`);\n }\n }\n\n // 2) next.config guidance (never auto-edited — users customize this file).\n const cfg = findNextConfig(cwd);\n const cfgLines = [\n `cacheHandler: require.resolve(\"./cache-incremental.cjs\"),`,\n ...(next.supportsCacheComponents\n ? [\n `cacheHandlers: { default: require.resolve(\"./cache-components.cjs\") },`,\n `cacheComponents: true,`,\n ]\n : []),\n `cacheMaxMemorySize: 0, // required for multi-instance correctness`,\n ];\n if (!cfg) {\n log(`${WARN} no next.config found — create one with:`);\n } else {\n const body = fs.readFileSync(cfg, \"utf8\");\n if (body.includes(\"cacheHandler\")) {\n log(`${OK} ${path.basename(cfg)} already references a cacheHandler — verify it points at the shims above`);\n } else {\n log(`${ACTION} add to ${path.basename(cfg)}:`);\n }\n if (cfg.endsWith(\".mjs\")) {\n log(`${WARN} ESM config: add import { createRequire } from \"module\"; const require = createRequire(import.meta.url);`);\n }\n }\n for (const l of cfgLines) log(` ${l}`);\n\n // 3) Env template.\n const envExample = path.join(cwd, \".env.example\");\n const envBlock = `\\n# @leejpsd/nextjs-cache-handler\\nREDIS_URL=redis://127.0.0.1:6379\\nDEPLOYMENT_VERSION=dev\\n`;\n if (fs.existsSync(envExample)) {\n const body = fs.readFileSync(envExample, \"utf8\");\n if (body.includes(\"REDIS_URL\")) {\n log(`${OK} .env.example already mentions REDIS_URL`);\n } else if (apply) {\n fs.appendFileSync(envExample, envBlock);\n log(`${OK} appended REDIS_URL / DEPLOYMENT_VERSION to .env.example`);\n } else {\n log(`${ACTION} would append REDIS_URL / DEPLOYMENT_VERSION to .env.example`);\n }\n } else {\n log(`${ACTION} set REDIS_URL and DEPLOYMENT_VERSION in every runtime environment`);\n }\n\n // 4) Agent rules injection (idempotent via markers).\n const rulesSrc = packagedFile(\"rules/nextjs-cache-rules.md\");\n const ruleTargets = [\"CLAUDE.md\", \"AGENTS.md\"]\n .map((f) => path.join(cwd, f))\n .filter((p) => fs.existsSync(p));\n if (rulesSrc && ruleTargets.length > 0) {\n const rules = `\\n${RULES_BEGIN}\\n${fs.readFileSync(rulesSrc, \"utf8\")}\\n${RULES_END}\\n`;\n for (const target of ruleTargets) {\n const body = fs.readFileSync(target, \"utf8\");\n if (body.includes(RULES_BEGIN)) {\n log(`${OK} ${path.basename(target)} already has the cache rules block`);\n } else if (apply) {\n fs.appendFileSync(target, rules);\n log(`${OK} appended cache rules to ${path.basename(target)}`);\n } else {\n log(`${ACTION} would append cache rules to ${path.basename(target)}`);\n }\n }\n } else if (ruleTargets.length === 0) {\n log(`${WARN} no CLAUDE.md/AGENTS.md found — skip rules injection (create one to guide your agent)`);\n }\n\n // 5) MCP registration — one file turns any MCP-capable agent (Claude\n // Code, Cursor, ...) into a cache operator via npx (no install needed).\n const mcpPath = path.join(cwd, \".mcp.json\");\n if (fs.existsSync(mcpPath)) {\n const body = fs.readFileSync(mcpPath, \"utf8\");\n if (body.includes(\"nextjs-cache-handler-mcp\")) {\n log(`${OK} .mcp.json already registers the cache MCP server`);\n } else {\n log(`${ACTION} .mcp.json exists — add the \"nextjs-cache\" server manually (see @leejpsd/nextjs-cache-handler-mcp README)`);\n }\n } else if (apply) {\n fs.writeFileSync(\n mcpPath,\n JSON.stringify(\n {\n mcpServers: {\n \"nextjs-cache\": {\n command: \"npx\",\n args: [\"-y\", \"@leejpsd/nextjs-cache-handler-mcp\"],\n env: {\n REDIS_URL: \"redis://127.0.0.1:6379\",\n DEPLOYMENT_VERSION: \"dev\",\n },\n },\n },\n },\n null,\n 2\n ) + \"\\n\"\n );\n log(`${OK} wrote .mcp.json — your agent now has cache_health/tag_state/... tools (edit REDIS_URL for real environments)`);\n } else {\n log(`${ACTION} would create .mcp.json registering @leejpsd/nextjs-cache-handler-mcp`);\n }\n\n // 6) Optional skill install.\n if (flags.has(\"--skills\")) {\n const skillSrc = packagedFile(\"skills/nextjs-redis-cache/SKILL.md\");\n if (skillSrc) {\n const dest = path.join(cwd, \".claude\", \"skills\", \"nextjs-redis-cache\", \"SKILL.md\");\n if (apply) {\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.copyFileSync(skillSrc, dest);\n log(`${OK} installed skill to .claude/skills/nextjs-redis-cache/`);\n } else {\n log(`${ACTION} would install skill to .claude/skills/nextjs-redis-cache/`);\n }\n }\n }\n\n log(`${OK} init ${apply ? \"complete\" : \"preview complete — re-run with --yes to apply\"}. Verify with: npx nextjs-cache-handler doctor`);\n return 0;\n}\n\n// ─── doctor ──────────────────────────────────────────────────────────────────\n\nexport async function doctor(ctx: Ctx): Promise<number> {\n const { args, log } = ctx;\n const urlIdx = args.indexOf(\"--url\");\n const url = urlIdx >= 0 ? args[urlIdx + 1] : process.env.REDIS_URL;\n if (!url) {\n log(`${ERR} no Redis URL — pass --url <redis-url> or set REDIS_URL`);\n return 1;\n }\n\n const deployment = process.env.DEPLOYMENT_VERSION;\n log(deployment ? `${OK} DEPLOYMENT_VERSION=${deployment}` : `${WARN} DEPLOYMENT_VERSION not set — keys will use the \"unversioned\" namespace`);\n\n let client: RedisClientLike;\n try {\n // Prefer node-redis; fall back to ioredis when only that peer is installed.\n try {\n client = await buildClient({ type: \"redis\", url });\n } catch (err) {\n if (/Cannot find module/.test((err as Error).message)) {\n client = await buildClient({ type: \"ioredis\", url });\n } else {\n throw err;\n }\n }\n if (!client.isOpen) await client.connect();\n } catch (err) {\n log(`${ERR} connect failed: ${(err as Error).message}`);\n log(`${ACTION} check the URL/network, or install a client: npm i redis (or ioredis)`);\n return 1;\n }\n\n try {\n const t0 = Date.now();\n await client.ping();\n log(`${OK} redis PING ${Date.now() - t0}ms (${url.replace(/\\/\\/[^@]*@/, \"//***@\")})`);\n\n const counts = new Map<string, number>();\n for await (const chunk of client.scanIterator({ MATCH: \"next-*\", COUNT: 500 })) {\n const keys = Array.isArray(chunk) ? chunk : [chunk];\n for (const k of keys) {\n const key = String(k);\n const m = key.match(/^(next-cache|next-incremental):([a-z-]+):/);\n const bucket = m ? `${m[1]}:${m[2]}` : \"other\";\n counts.set(bucket, (counts.get(bucket) ?? 0) + 1);\n }\n }\n if (counts.size === 0) {\n log(`${WARN} no next-* keys found — cache not yet exercised (or a custom keyPrefix is in use)`);\n } else {\n for (const [bucket, n] of [...counts.entries()].sort()) {\n log(`${OK} ${bucket}* — ${n} keys`);\n }\n }\n\n // Round-trip probe in an isolated namespace.\n const probeKey = `next-cache:doctor:${Date.now()}`;\n await client.set(probeKey, \"ok\", { EX: 30 });\n const back = await client.get(probeKey);\n await client.del(probeKey);\n log(back === \"ok\" ? `${OK} write/read round-trip` : `${ERR} round-trip failed`);\n return back === \"ok\" ? 0 : 1;\n } finally {\n client.dispose?.();\n }\n}\n\n\n// ─── seed ────────────────────────────────────────────────────────────────────\n\nexport async function seed(ctx: Ctx): Promise<number> {\n const { args, flags, log } = ctx;\n const urlIdx = args.indexOf(\"--url\");\n const url = urlIdx >= 0 ? args[urlIdx + 1] : process.env.REDIS_URL;\n if (!url) {\n log(`${ERR} no Redis URL — pass --url <redis-url> or set REDIS_URL`);\n return 1;\n }\n const flagVal = (name: string): string | undefined => {\n const i = args.indexOf(name);\n return i >= 0 ? args[i + 1] : undefined;\n };\n const dir = flagVal(\"--dir\") ?? \".next\";\n const keyPrefix = flagVal(\"--key-prefix\");\n const namespace = flagVal(\"--namespace\");\n const compression = flagVal(\"--compression\") as \"gzip\" | \"brotli\" | undefined;\n const hashTag = flags.has(\"--hash-tag\");\n\n const ns =\n namespace ??\n process.env.DEPLOYMENT_VERSION ??\n process.env.GIT_HASH ??\n \"unversioned\";\n if (ns === \"unversioned\") {\n log(`${WARN} no namespace — seeding into \"unversioned\" (set DEPLOYMENT_VERSION or pass --namespace)`);\n }\n // Print the exact key shape so a config mismatch with the runtime handler\n // (custom keyPrefix / hashTag) is visible instead of silently seeding\n // keys the app never reads.\n log(`${OK} target keys: ${keyPrefix ?? \"next-incremental:\"}entry:${hashTag ? `{${ns}}` : ns}:*`);\n\n const seedOpts = {\n dir,\n buildNamespace: ns,\n ...(keyPrefix ? { keyPrefix } : {}),\n ...(compression ? { compression } : {}),\n ...(hashTag ? { hashTag: true } : {}),\n };\n const report = (summary: Awaited<ReturnType<typeof seedBuildOutput>>): number => {\n log(`${OK} seeded: ${summary.routes} app routes, ${summary.pages} pages routes, ${summary.fetch} fetch entries`);\n if (summary.skippedExisting > 0)\n log(`${OK} left ${summary.skippedExisting} newer live entries untouched (NX)`);\n if (summary.skippedRouteHandlers > 0)\n log(`${OK} ${summary.skippedRouteHandlers} prerendered route handlers not seeded (by design)`);\n if (summary.skippedIncomplete > 0)\n log(`${WARN} skipped ${summary.skippedIncomplete} routes (incomplete files or PPR resume state)`);\n for (const e of summary.errors.slice(0, 5)) log(`${WARN} ${e}`);\n return summary.errors.length > 0 ? 1 : 0;\n };\n\n try {\n return report(\n await seedBuildOutput({ client: { type: \"redis\", url }, ...seedOpts })\n );\n } catch (err) {\n const msg = (err as Error).message;\n if (/Cannot find module 'redis'/.test(msg)) {\n // Retry with ioredis when only that peer is installed.\n try {\n return report(\n await seedBuildOutput({ client: { type: \"ioredis\", url }, ...seedOpts })\n );\n } catch (err2) {\n log(`${ERR} ${(err2 as Error).message}`);\n return 1;\n }\n }\n log(`${ERR} ${msg}`);\n return 1;\n }\n}\n\n// ─── entry ───────────────────────────────────────────────────────────────────\n\nexport async function main(argv: string[] = process.argv.slice(2)): Promise<number> {\n const [cmd, ...rest] = argv;\n const ctx: Ctx = {\n cwd: process.cwd(),\n args: rest,\n flags: new Set(rest.filter((a) => a.startsWith(\"--\"))),\n log: (l) => console.log(l),\n };\n switch (cmd) {\n case \"init\":\n return init(ctx);\n case \"doctor\":\n return doctor(ctx);\n case \"seed\":\n return seed(ctx);\n default:\n console.log(`nextjs-cache-handler <command>\n\nCommands:\n init [--yes] [--dry-run] [--skills] wire handlers into this Next.js app\n doctor [--url <redis-url>] connectivity + cache diagnostics\n seed [--dir .next] [--url <u>] [--namespace <ns>] [--key-prefix <p>] [--hash-tag] [--compression gzip|brotli]\n seed prerendered build output into Redis\n\nAgent setup instructions:\n https://raw.githubusercontent.com/leejpsd/nextjs-cache-handler/main/setup-instructions/setup.md`);\n return cmd ? 1 : 0;\n }\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 * Build-output cache seeding.\n *\n * `next build` prerenders pages and fetch-cache entries into `.next/`, but a\n * fresh deployment's Redis is empty — every first request pays a full\n * regeneration (and N instances pay it N times). `seedBuildOutput()` walks\n * the build output and inserts it into Redis in the exact record format the\n * incremental handler reads, using **NX semantics**: an entry that a running\n * instance has already written (necessarily newer) is never overwritten.\n *\n * Run it once per deploy, after `next build` and before (or while) traffic\n * shifts — e.g. as a Docker entrypoint step or CI job:\n *\n * npx nextjs-cache-handler seed # uses REDIS_URL / DEPLOYMENT_VERSION\n * npx nextjs-cache-handler seed --dir .next\n *\n * Seeds:\n * - App Router routes (`.next/server/app/<route>.{html,rsc,meta}` +\n * PPR `.segments/`) → APP_PAGE records\n * - Pages Router routes (`.next/server/pages/<route>.{html,json}`) → PAGES\n * - fetch cache (`.next/cache/fetch-cache/<hash>`) → FETCH records\n *\n * Route keys: Next.js 16.3.8+ scopes response-cache keys by source route\n * (`/route-cache/<KIND>/<hash>/$/<path>`) and never asks a custom handler\n * for a bare pathname. The build records the exact key in each artifact's\n * `.meta` (`routeCache.key`), so routes are seeded under that key when it is\n * present. Builds from older Next versions carry no such key and are looked\n * up by normalized page path (`/` is `/index`), which is what gets used then.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { buildClient } from \"../shared/client/index.js\";\nimport { compressValue } from \"../shared/compress.js\";\nimport { buildKey, resolveBuildNamespace } from \"../shared/namespace.js\";\nimport { serializeCacheRecord } from \"../incremental/serialize.js\";\nimport type {\n Logger,\n RedisClientConfig,\n RedisClientFactory,\n RedisClientLike,\n} from \"../types.js\";\n\nconst ONE_YEAR_SEC = 60 * 60 * 24 * 365;\nconst MIN_TTL_SEC = 60;\nconst DEFAULT_KEY_PREFIX = \"next-incremental:\";\n\nexport interface SeedOptions {\n client: RedisClientFactory | RedisClientConfig;\n /** Path to the build output. Default: `./.next`. */\n dir?: string;\n keyPrefix?: string;\n buildNamespace?: string | (() => string);\n compression?: \"gzip\" | \"brotli\";\n hashTag?: boolean;\n logger?: Pick<Logger, \"warn\">;\n}\n\nexport interface SeedSummary {\n /** App Router routes written. */\n routes: number;\n /** Pages Router routes written. */\n pages: number;\n /** fetch-cache entries written. */\n fetch: number;\n /** Entries skipped because a (newer) live entry already existed (NX). */\n skippedExisting: number;\n /** Routes skipped because their files were incomplete or PPR-postponed. */\n skippedIncomplete: number;\n /** Prerendered route handlers (.body) — never seeded, by design. */\n skippedRouteHandlers: number;\n errors: string[];\n}\n\ninterface ManifestRoute {\n initialRevalidateSeconds?: number | false;\n dataRoute?: string | null;\n srcRoute?: string | null;\n}\n\nfunction clampTtl(revalidate: number | false | undefined): number {\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\n/**\n * Mirrors Next's `normalizePagePath` for a concrete prerendered route:\n * `/` → `/index`, `/index/sub` → `/index/index/sub`. This is where the build\n * stores the route's artifacts and, before Next.js 16.3.8, the key Next's\n * IncrementalCache derives for it.\n */\nfunction routeToFileBase(route: string): string {\n if (route === \"/\") return \"/index\";\n if (/^\\/index(\\/|$)/.test(route)) return `/index${route}`;\n return route;\n}\n\nfunction readMeta(file: string): {\n status?: number;\n headers?: Record<string, string>;\n segmentPaths?: string[];\n postponed?: string;\n routeCache?: { key?: unknown };\n} | null {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\")) as ReturnType<typeof readMeta>;\n } catch {\n return null;\n }\n}\n\n/**\n * The key the runtime will look this route up by. Next.js 16.3.8+ writes it\n * into the build artifact's `.meta`; without it (older Next, or a missing or\n * malformed `.meta`) the lookup key is the normalized page path, i.e. the\n * same `base` the artifact files are stored under.\n */\nfunction resolveRouteKey(base: string, meta: ReturnType<typeof readMeta>): string {\n const key = meta?.routeCache?.key;\n return typeof key === \"string\" && key.length > 0 ? key : base;\n}\n\nasync function writeRecord(\n client: RedisClientLike,\n key: string,\n value: unknown,\n revalidateSec: number | false | undefined,\n opts: Required<Pick<SeedOptions, \"keyPrefix\" | \"hashTag\">> & {\n ns: string;\n compression?: \"gzip\" | \"brotli\";\n }\n): Promise<\"written\" | \"skipped\"> {\n const record = {\n lastModified: Date.now(),\n value,\n revalidateSec: clampTtl(revalidateSec),\n };\n const redisKey = buildKey(`${opts.keyPrefix}entry:`, opts.ns, key, opts.hashTag);\n const payload = await compressValue(\n serializeCacheRecord(record),\n opts.compression\n );\n const result = await client.set(redisKey, payload, {\n EX: clampTtl(revalidateSec),\n NX: true,\n });\n // Redis returns null (nil) when NX blocks the write.\n return result === null ? \"skipped\" : \"written\";\n}\n\nexport async function seedBuildOutput(options: SeedOptions): Promise<SeedSummary> {\n const dir = path.resolve(options.dir ?? \".next\");\n const keyPrefix = options.keyPrefix ?? DEFAULT_KEY_PREFIX;\n const hashTag = options.hashTag ?? false;\n const ns = resolveBuildNamespace(options.buildNamespace);\n const warn = options.logger?.warn ?? (() => {});\n const summary: SeedSummary = {\n routes: 0,\n pages: 0,\n fetch: 0,\n skippedExisting: 0,\n skippedIncomplete: 0,\n skippedRouteHandlers: 0,\n errors: [],\n };\n\n const manifestPath = path.join(dir, \"prerender-manifest.json\");\n if (!fs.existsSync(manifestPath)) {\n throw new Error(\n `[next-cache] no prerender-manifest.json in ${dir} — run \\`next build\\` first`\n );\n }\n const manifest = JSON.parse(fs.readFileSync(manifestPath, \"utf8\")) as {\n routes?: Record<string, ManifestRoute>;\n };\n\n const client = await buildClient(options.client);\n if (!client.isOpen) await client.connect();\n\n const writeOpts = { keyPrefix, hashTag, ns, ...(options.compression ? { compression: options.compression } : {}) };\n\n try {\n // ── 1) Prerendered routes ────────────────────────────────────────────────\n for (const [route, info] of Object.entries(manifest.routes ?? {})) {\n try {\n const isPages = typeof info.dataRoute === \"string\" && info.dataRoute.endsWith(\".json\");\n const base = routeToFileBase(route);\n\n if (isPages) {\n const html = path.join(dir, \"server\", \"pages\", `${base.slice(1)}.html`);\n const data = path.join(dir, \"server\", \"pages\", `${base.slice(1)}.json`);\n const pagesMeta = path.join(dir, \"server\", \"pages\", `${base.slice(1)}.meta`);\n if (!fs.existsSync(html)) {\n summary.skippedIncomplete += 1;\n continue;\n }\n const value = {\n kind: \"PAGES\",\n html: fs.readFileSync(html, \"utf8\"),\n pageData: fs.existsSync(data)\n ? (JSON.parse(fs.readFileSync(data, \"utf8\")) as unknown)\n : {},\n headers: undefined,\n status: undefined,\n };\n const key = resolveRouteKey(base, readMeta(pagesMeta));\n const r = await writeRecord(client, key, value, info.initialRevalidateSeconds, writeOpts);\n if (r === \"written\") summary.pages += 1;\n else summary.skippedExisting += 1;\n continue;\n }\n\n // App Router\n const htmlPath = path.join(dir, \"server\", \"app\", `${base.slice(1)}.html`);\n const rscPath = path.join(dir, \"server\", \"app\", `${base.slice(1)}.rsc`);\n const metaPath = path.join(dir, \"server\", \"app\", `${base.slice(1)}.meta`);\n if (!fs.existsSync(htmlPath) || !fs.existsSync(metaPath)) {\n // Prerendered route handlers emit .body/.meta instead of .html —\n // they are intentionally not seeded, and not \"incomplete\".\n if (fs.existsSync(path.join(dir, \"server\", \"app\", `${base.slice(1)}.body`))) {\n summary.skippedRouteHandlers += 1;\n } else {\n summary.skippedIncomplete += 1;\n }\n continue;\n }\n const meta = readMeta(metaPath) ?? {};\n if (meta.postponed) {\n // PPR routes with resume state cannot be faithfully seeded from\n // static files (the runtime needs `postponed` to resume dynamic\n // holes, and Next intentionally omits the .rsc for them). Serving\n // a seeded copy would freeze the unresolved shell as final HTML.\n summary.skippedIncomplete += 1;\n continue;\n }\n\n let segmentData: Map<string, Buffer> | undefined;\n if (Array.isArray(meta.segmentPaths) && meta.segmentPaths.length > 0) {\n const segDir = path.join(dir, \"server\", \"app\", `${base.slice(1)}.segments`);\n segmentData = new Map();\n for (const segPath of meta.segmentPaths) {\n const segFile = path.join(segDir, `${segPath.slice(1)}.segment.rsc`);\n if (fs.existsSync(segFile)) {\n segmentData.set(segPath, fs.readFileSync(segFile));\n }\n }\n if (segmentData.size !== meta.segmentPaths.length) {\n // Partial segment sets would break PPR resumes — safer to skip.\n summary.skippedIncomplete += 1;\n continue;\n }\n }\n\n const value: Record<string, unknown> = {\n kind: \"APP_PAGE\",\n html: fs.readFileSync(htmlPath, \"utf8\"),\n rscData: fs.existsSync(rscPath) ? fs.readFileSync(rscPath) : undefined,\n headers: meta.headers,\n status: meta.status,\n };\n if (segmentData) value.segmentData = segmentData;\n\n const key = resolveRouteKey(base, meta);\n const r = await writeRecord(client, key, value, info.initialRevalidateSeconds, writeOpts);\n if (r === \"written\") summary.routes += 1;\n else summary.skippedExisting += 1;\n } catch (err) {\n summary.errors.push(`${route}: ${(err as Error).message}`);\n warn(\"seed: route failed\", { route, message: (err as Error).message });\n }\n }\n\n // ── 2) fetch cache ───────────────────────────────────────────────────────\n const fetchDir = path.join(dir, \"cache\", \"fetch-cache\");\n if (fs.existsSync(fetchDir)) {\n for (const file of fs.readdirSync(fetchDir)) {\n if (file.startsWith(\".\")) continue;\n try {\n const raw = fs.readFileSync(path.join(fetchDir, file), \"utf8\");\n const value = JSON.parse(raw) as { kind?: string; revalidate?: number };\n if (value.kind !== \"FETCH\") continue;\n const r = await writeRecord(client, file, value, value.revalidate, writeOpts);\n if (r === \"written\") summary.fetch += 1;\n else summary.skippedExisting += 1;\n } catch (err) {\n summary.errors.push(`fetch:${file}: ${(err as Error).message}`);\n }\n }\n }\n } finally {\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 */\n }\n }\n\n return summary;\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 * 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 * 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(this: Record<string, unknown>, key: string, value: unknown): unknown {\n // Buffer.prototype.toJSON runs BEFORE the replacer (JSON spec), so `value`\n // is already { type: \"Buffer\", data: number[] } here. `this[key]` is the\n // pre-toJSON original — the only place the real Buffer is still visible.\n const raw = this[key];\n if (Buffer.isBuffer(raw)) {\n const env: BufferEnvelope = {\n __type: \"Buffer\",\n data: raw.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/cli/index.js CHANGED
@@ -403,7 +403,9 @@ function clampTtl(revalidate) {
403
403
  return MIN_TTL_SEC;
404
404
  }
405
405
  function routeToFileBase(route) {
406
- return route === "/" ? "/index" : route;
406
+ if (route === "/") return "/index";
407
+ if (/^\/index(\/|$)/.test(route)) return `/index${route}`;
408
+ return route;
407
409
  }
408
410
  function readMeta(file) {
409
411
  try {
@@ -412,6 +414,10 @@ function readMeta(file) {
412
414
  return null;
413
415
  }
414
416
  }
417
+ function resolveRouteKey(base, meta) {
418
+ const key = meta?.routeCache?.key;
419
+ return typeof key === "string" && key.length > 0 ? key : base;
420
+ }
415
421
  async function writeRecord(client, key, value, revalidateSec, opts) {
416
422
  const record = {
417
423
  lastModified: Date.now(),
@@ -463,6 +469,7 @@ async function seedBuildOutput(options) {
463
469
  if (isPages) {
464
470
  const html = path4.join(dir, "server", "pages", `${base.slice(1)}.html`);
465
471
  const data = path4.join(dir, "server", "pages", `${base.slice(1)}.json`);
472
+ const pagesMeta = path4.join(dir, "server", "pages", `${base.slice(1)}.meta`);
466
473
  if (!fs.existsSync(html)) {
467
474
  summary.skippedIncomplete += 1;
468
475
  continue;
@@ -474,7 +481,8 @@ async function seedBuildOutput(options) {
474
481
  headers: void 0,
475
482
  status: void 0
476
483
  };
477
- const r2 = await writeRecord(client, route, value2, info.initialRevalidateSeconds, writeOpts);
484
+ const key2 = resolveRouteKey(base, readMeta(pagesMeta));
485
+ const r2 = await writeRecord(client, key2, value2, info.initialRevalidateSeconds, writeOpts);
478
486
  if (r2 === "written") summary.pages += 1;
479
487
  else summary.skippedExisting += 1;
480
488
  continue;
@@ -518,7 +526,8 @@ async function seedBuildOutput(options) {
518
526
  status: meta.status
519
527
  };
520
528
  if (segmentData) value.segmentData = segmentData;
521
- const r = await writeRecord(client, route, value, info.initialRevalidateSeconds, writeOpts);
529
+ const key = resolveRouteKey(base, meta);
530
+ const r = await writeRecord(client, key, value, info.initialRevalidateSeconds, writeOpts);
522
531
  if (r === "written") summary.routes += 1;
523
532
  else summary.skippedExisting += 1;
524
533
  } catch (err) {