@gigadrive/network-config 4.3.4 → 4.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/nextjs-adapter.js +35 -0
- package/dist/nextjs-adapter.js.map +1 -1
- package/dist/nextjs-adapter.mjs +35 -0
- package/dist/nextjs-adapter.mjs.map +1 -1
- package/dist/nextjs-cache-components-handler.js +1 -0
- package/dist/nextjs-cache-components-handler.js.map +1 -1
- package/dist/nextjs-cache-components-handler.mjs +1 -0
- package/dist/nextjs-cache-components-handler.mjs.map +1 -1
- package/dist/nextjs-cache-handler.js +1 -0
- package/dist/nextjs-cache-handler.js.map +1 -1
- package/dist/nextjs-cache-handler.mjs +1 -0
- package/dist/nextjs-cache-handler.mjs.map +1 -1
- package/package.json +2 -2
package/dist/nextjs-adapter.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(nextjs_adapter_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(nextjs_adapter_exports);
|
|
37
37
|
var import_promises = require("fs/promises");
|
|
38
|
+
var import_node_module = require("module");
|
|
38
39
|
var import_node_path = __toESM(require("path"));
|
|
39
40
|
var import_node_url = require("url");
|
|
40
41
|
var import_meta = {};
|
|
@@ -120,6 +121,37 @@ var aggregateServerDescriptor = (outputs) => {
|
|
|
120
121
|
...Object.keys(env).length > 0 ? { env } : {}
|
|
121
122
|
};
|
|
122
123
|
};
|
|
124
|
+
async function ensureStandaloneServerTraces(projectDir, repoRoot, distDir, config) {
|
|
125
|
+
const aggregateTracePath = import_node_path.default.join(distDir, "next-server.js.nft.json");
|
|
126
|
+
try {
|
|
127
|
+
await (0, import_promises.access)(aggregateTracePath);
|
|
128
|
+
return;
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
let collectBuildTracesModule;
|
|
132
|
+
try {
|
|
133
|
+
const projectRequire = (0, import_node_module.createRequire)(import_node_path.default.join(projectDir, "package.json"));
|
|
134
|
+
collectBuildTracesModule = projectRequire("next/dist/build/collect-build-traces");
|
|
135
|
+
} catch (error) {
|
|
136
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
137
|
+
throw new Error(
|
|
138
|
+
`Next.js did not emit ${aggregateTracePath} and the Gigadrive adapter could not load next/dist/build/collect-build-traces from the project to regenerate it: ${message}`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
await collectBuildTracesModule.collectBuildTraces({
|
|
143
|
+
dir: projectDir,
|
|
144
|
+
config,
|
|
145
|
+
distDir,
|
|
146
|
+
edgeRuntimeRoutes: {},
|
|
147
|
+
staticPages: [],
|
|
148
|
+
outputFileTracingRoot: config.outputFileTracingRoot ?? repoRoot
|
|
149
|
+
});
|
|
150
|
+
} catch (error) {
|
|
151
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
152
|
+
throw new Error(`Regenerating the Next.js standalone server traces (${aggregateTracePath}) failed: ${message}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
123
155
|
var normalizeImages = (config) => {
|
|
124
156
|
if (config.images.unoptimized) return void 0;
|
|
125
157
|
return {
|
|
@@ -228,6 +260,9 @@ var gigadriveNextAdapter = {
|
|
|
228
260
|
await writeManifest(manifest2);
|
|
229
261
|
return;
|
|
230
262
|
}
|
|
263
|
+
if (config.output === "standalone") {
|
|
264
|
+
await ensureStandaloneServerTraces(projectDir, repoRoot, distDir, config);
|
|
265
|
+
}
|
|
231
266
|
const prerenders = await Promise.all(
|
|
232
267
|
outputs.prerenders.map((output) => serializePrerenderOutput(repoRoot, output))
|
|
233
268
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nextjs-adapter.ts"],"sourcesContent":["import type { NextAdapter } from 'next';\nimport { access, mkdir, realpath, stat, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { NormalizedImagePolicy } from './image-policy';\nimport type {\n GigadriveNextBuildManifestV1,\n GigadriveNextBuildManifestV2Export,\n GigadriveNextBuildManifestV2Standalone,\n GigadriveNextPrerenderOutput,\n GigadriveNextServerDescriptor,\n GigadriveNextStaticAssetPrefix,\n JsonValue,\n} from './nextjs-manifest';\n\ntype BuildCompleteContext = Parameters<NonNullable<NextAdapter['onBuildComplete']>>[0];\ntype NextRouteOutput =\n | BuildCompleteContext['outputs']['pages'][number]\n | BuildCompleteContext['outputs']['pagesApi'][number]\n | BuildCompleteContext['outputs']['appPages'][number]\n | BuildCompleteContext['outputs']['appRoutes'][number]\n | NonNullable<BuildCompleteContext['outputs']['middleware']>;\ntype NextPrerenderOutput = BuildCompleteContext['outputs']['prerenders'][number];\n\nconst PRODUCTION_BUILD_PHASE = 'phase-production-build';\nconst runtimeDirectory = typeof __dirname === 'string' ? __dirname : path.dirname(fileURLToPath(import.meta.url));\n\nconst runtimeModulePath = (environmentName: string, fileName: string): string =>\n process.env[environmentName] ?? path.join(runtimeDirectory, fileName);\n\nconst CACHE_HANDLER_PATH = () => runtimeModulePath('GIGADRIVE_NEXT_CACHE_HANDLER_PATH', 'nextjs-cache-handler.js');\nconst CACHE_COMPONENTS_HANDLER_PATH = () =>\n runtimeModulePath('GIGADRIVE_NEXT_CACHE_COMPONENTS_HANDLER_PATH', 'nextjs-cache-components-handler.js');\nconst IMAGE_LOADER_PATH = () => runtimeModulePath('GIGADRIVE_NEXT_IMAGE_LOADER_PATH', 'nextjs-image-loader.js');\n\nconst toJsonValue = (value: unknown): JsonValue => {\n const serialized = JSON.stringify(value);\n return serialized === undefined ? null : (JSON.parse(serialized) as JsonValue);\n};\n\n/**\n * Next 16.2 introduced the adapter hooks (`modifyConfig` + `onBuildComplete`) and\n * the `cacheHandler`/`cacheHandlers`/`cacheComponents` config fields we inject.\n * Earlier releases keep the legacy standalone-only behavior with no injection.\n */\nconst supportsManagedRuntime = (nextVersion: string | undefined): boolean => {\n if (!nextVersion) return false;\n const [majorPart, minorPart] = nextVersion.split('.');\n const major = Number.parseInt(majorPart ?? '', 10);\n const minor = Number.parseInt(minorPart ?? '', 10);\n return Number.isFinite(major) && Number.isFinite(minor) && (major > 16 || (major === 16 && minor >= 2));\n};\n\n/**\n * Highest Next major validated to allow `output: 'standalone'` together with an\n * adapter. Next's own build source warns the combination \"might not be allowed\"\n * in a future release. We always emit `output: 'standalone'` on the managed path\n * (there is no per-route fallback to degrade to), so if a future major forbids\n * it the build fails loudly at `next build` rather than silently misdeploying.\n * The network canary drift test tracks releases past this bound.\n */\nconst MANAGED_STANDALONE_VALIDATED_MAX_MAJOR = 16;\n\nconst toPortableRelativePath = (from: string, to: string, allowCurrentDirectory = false): string => {\n const resolvedFrom = path.resolve(from);\n const resolvedTo = path.resolve(path.isAbsolute(to) ? to : path.join(from, to));\n const relativePath = path.relative(resolvedFrom, resolvedTo).replaceAll(path.sep, '/');\n const normalized = relativePath === '' ? '.' : relativePath;\n if (\n (!allowCurrentDirectory && normalized === '.') ||\n normalized.startsWith('/') ||\n /^[A-Za-z]:/.test(normalized) ||\n normalized.split('/').some((segment) => segment === '..')\n ) {\n throw new Error(`Next.js adapter output is outside the repository root: ${to}`);\n }\n return normalized;\n};\n\nasync function resolveReadablePath(repoRoot: string, filePath: string) {\n const absolutePath = path.resolve(path.isAbsolute(filePath) ? filePath : path.join(repoRoot, filePath));\n const portablePath = toPortableRelativePath(repoRoot, absolutePath);\n await access(absolutePath);\n // Validate the symlink-resolved location as well; the call throws when the\n // real path escapes the repository root.\n const resolvedPath = await realpath(absolutePath);\n void toPortableRelativePath(repoRoot, resolvedPath);\n const fileStat = await stat(absolutePath);\n return { portablePath, fileStat };\n}\n\nasync function requireReadableFile(repoRoot: string, filePath: string): Promise<string> {\n const { portablePath, fileStat } = await resolveReadablePath(repoRoot, filePath);\n if (!fileStat.isFile()) throw new Error(`Next.js adapter output is not a readable file: ${filePath}`);\n return portablePath;\n}\n\nconst serializePrerenderOutput = async (\n repoRoot: string,\n output: NextPrerenderOutput\n): Promise<GigadriveNextPrerenderOutput> => {\n const { bypassFor, ...prerenderConfig } = output.config;\n return {\n id: output.id,\n type: 'PRERENDER',\n pathname: output.pathname,\n parentOutputId: output.parentOutputId,\n groupId: output.groupId,\n ...(output.pprChain ? { pprChain: output.pprChain } : {}),\n ...(output.parentFallbackMode !== undefined ? { parentFallbackMode: toJsonValue(output.parentFallbackMode) } : {}),\n ...(output.fallback\n ? {\n fallback: {\n ...(output.fallback.filePath\n ? { filePath: await requireReadableFile(repoRoot, output.fallback.filePath) }\n : {}),\n ...(output.fallback.initialStatus !== undefined ? { initialStatus: output.fallback.initialStatus } : {}),\n ...(output.fallback.initialHeaders ? { initialHeaders: output.fallback.initialHeaders } : {}),\n ...(output.fallback.initialExpiration !== undefined\n ? { initialExpiration: output.fallback.initialExpiration }\n : {}),\n ...(output.fallback.initialRevalidate !== undefined\n ? { initialRevalidate: output.fallback.initialRevalidate }\n : {}),\n ...(output.fallback.postponedState !== undefined ? { postponedState: output.fallback.postponedState } : {}),\n },\n }\n : {}),\n config: {\n ...prerenderConfig,\n ...(bypassFor ? { bypassFor: toJsonValue(bypassFor) as JsonValue[] } : {}),\n },\n };\n};\n\n/**\n * Collapses per-route runtime config onto the one standalone server. `maxDuration`\n * becomes the max across routes (one function honors one limit); `env` is the union\n * of every route's declared env (the single server runs them all in-process).\n */\nconst aggregateServerDescriptor = (outputs: NextRouteOutput[]): GigadriveNextServerDescriptor => {\n let maxDuration: number | undefined;\n const env: Record<string, string> = {};\n for (const output of outputs) {\n if (output.config.maxDuration !== undefined) {\n maxDuration = Math.max(maxDuration ?? 0, output.config.maxDuration);\n }\n if (output.config.env) Object.assign(env, output.config.env);\n }\n return {\n ...(maxDuration !== undefined ? { maxDuration } : {}),\n ...(Object.keys(env).length > 0 ? { env } : {}),\n };\n};\n\nconst normalizeImages = (config: BuildCompleteContext['config']): NormalizedImagePolicy | undefined => {\n if (config.images.unoptimized) return undefined;\n return {\n localPatterns: config.images.localPatterns ?? [{ pathname: '/**' }],\n remotePatterns: config.images.remotePatterns.map((pattern) => {\n if (pattern instanceof URL) {\n return {\n protocol: pattern.protocol === 'http:' ? ('http' as const) : ('https' as const),\n hostname: pattern.hostname,\n port: pattern.port,\n pathname: pattern.pathname,\n search: pattern.search,\n };\n }\n return { ...pattern };\n }),\n widths: [...new Set([...config.images.deviceSizes, ...config.images.imageSizes])].sort((a, b) => a - b),\n heights: [],\n qualities: config.images.qualities ?? [75],\n formats: config.images.formats,\n minimumCacheTTL: config.images.minimumCacheTTL,\n dangerouslyAllowSVG: config.images.dangerouslyAllowSVG,\n contentSecurityPolicy: config.images.contentSecurityPolicy,\n contentDispositionType: config.images.contentDispositionType,\n maximumRedirects: config.images.maximumRedirects,\n maximumResponseBody: config.images.maximumResponseBody,\n variants: {},\n };\n};\n\n/**\n * Next.js deployment adapter used automatically by Gigadrive Network build workers.\n *\n * Next 16.2 and newer run the entire deployment as a single `output: 'standalone'`\n * server (one function per deployment) while the injected cache handlers, image\n * loader, and this hook's `onBuildComplete` metadata keep ISR, PPR, `use cache`,\n * and image optimization working through the platform's durable runtime-cache and\n * edge image services. Older releases retain the legacy standalone behavior without\n * the managed-runtime injections.\n */\nconst gigadriveNextAdapter: NextAdapter = {\n name: 'Gigadrive Network',\n\n modifyConfig(config, { phase, nextVersion }) {\n if (phase !== PRODUCTION_BUILD_PHASE) return config;\n\n const deploymentId = config.deploymentId ?? process.env.GIGADRIVE_DEPLOYMENT_ID;\n if (!supportsManagedRuntime(nextVersion)) {\n return {\n ...config,\n ...(deploymentId ? { deploymentId } : {}),\n output: config.output === 'export' ? 'export' : 'standalone',\n };\n }\n if (config.output === 'export') {\n return { ...config, ...(deploymentId ? { deploymentId } : {}) };\n }\n\n const injectCacheHandler = config.cacheHandler === undefined;\n const injectCacheComponentHandlers = config.cacheHandlers === undefined;\n const images = config.images;\n const injectImageLoader =\n images !== undefined && images.unoptimized !== true && images.loader === 'default' && !images.loaderFile;\n\n return {\n ...config,\n ...(deploymentId ? { deploymentId } : {}),\n // Run the whole deployment as one standalone Next server rather than a\n // serverless function per route. `onBuildComplete` still fires under\n // standalone (Next >= 16.2), and the standalone server natively honors the\n // injected cache handlers and resumes PPR from its incremental cache, so\n // ISR/PPR/`use cache` stay durable via the remote runtime-cache service.\n // Validated on Next 16.2.x (see MANAGED_STANDALONE_VALIDATED_MAX_MAJOR);\n // a future major that forbids adapter + standalone fails loudly at build.\n output: 'standalone',\n ...(injectCacheHandler ? { cacheHandler: CACHE_HANDLER_PATH() } : {}),\n ...(injectCacheComponentHandlers\n ? {\n cacheHandlers: {\n default: CACHE_COMPONENTS_HANDLER_PATH(),\n remote: CACHE_COMPONENTS_HANDLER_PATH(),\n },\n }\n : {}),\n ...(injectCacheHandler || injectCacheComponentHandlers ? { cacheMaxMemorySize: 0 } : {}),\n ...(injectImageLoader\n ? {\n images: {\n ...images,\n loader: 'custom',\n loaderFile: IMAGE_LOADER_PATH(),\n },\n }\n : {}),\n };\n },\n\n async onBuildComplete({ projectDir, repoRoot, distDir, config, nextVersion, buildId, routing, outputs }) {\n const metadataDirectory = path.join(projectDir, '.gigadrive');\n await mkdir(metadataDirectory, { recursive: true });\n const manifestPath = path.join(metadataDirectory, 'nextjs.json');\n const writeManifest = (manifest: unknown) =>\n writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8');\n\n if (!supportsManagedRuntime(nextVersion)) {\n const manifest: GigadriveNextBuildManifestV1 = {\n version: 1,\n output: config.output === 'export' ? 'export' : 'standalone',\n distDir: toPortableRelativePath(projectDir, distDir),\n repoRootToProject: toPortableRelativePath(repoRoot, projectDir, true),\n nextVersion,\n buildId,\n };\n await writeManifest(manifest);\n return;\n }\n\n const portableDistDir = toPortableRelativePath(projectDir, distDir);\n const repoRootToProject = toPortableRelativePath(repoRoot, projectDir, true);\n\n if (config.output === 'export') {\n const manifest: GigadriveNextBuildManifestV2Export = {\n version: 2,\n mode: 'export',\n distDir: portableDistDir,\n repoRootToProject,\n nextVersion,\n buildId,\n };\n await writeManifest(manifest);\n return;\n }\n\n const prerenders = await Promise.all(\n outputs.prerenders.map((output) => serializePrerenderOutput(repoRoot, output))\n );\n const server = aggregateServerDescriptor([\n ...outputs.pages,\n ...outputs.pagesApi,\n ...outputs.appPages,\n ...outputs.appRoutes,\n ...(outputs.middleware ? [outputs.middleware] : []),\n ]);\n const images = normalizeImages(config);\n // `.next/static` is thousands of content-hashed, immutable chunks. Register\n // the whole subtree as one edge-served prefix instead of enumerating files.\n const staticAssets: GigadriveNextStaticAssetPrefix[] = [\n { sourceDir: `${portableDistDir}/static`, urlPrefix: '_next/static', immutable: true },\n ];\n\n const manifest: GigadriveNextBuildManifestV2Standalone = {\n version: 2,\n mode: 'standalone-v2',\n distDir: portableDistDir,\n repoRootToProject,\n nextVersion,\n buildId,\n server,\n config: {\n basePath: config.basePath,\n trailingSlash: config.trailingSlash,\n cacheComponents: config.cacheComponents,\n ...(config.i18n ? { i18n: toJsonValue(config.i18n) } : {}),\n ...(images ? { images } : {}),\n },\n routing: {\n beforeMiddleware: toJsonValue(routing.beforeMiddleware) as JsonValue[],\n beforeFiles: toJsonValue(routing.beforeFiles) as JsonValue[],\n afterFiles: toJsonValue(routing.afterFiles) as JsonValue[],\n dynamicRoutes: toJsonValue(routing.dynamicRoutes) as JsonValue[],\n onMatch: toJsonValue(routing.onMatch) as JsonValue[],\n fallback: toJsonValue(routing.fallback) as JsonValue[],\n shouldNormalizeNextData: routing.shouldNormalizeNextData,\n rsc: toJsonValue(routing.rsc),\n },\n outputs: { prerenders, staticAssets },\n };\n await writeManifest(manifest);\n },\n};\n\nexport { MANAGED_STANDALONE_VALIDATED_MAX_MAJOR };\nexport default gigadriveNextAdapter;\n"],"mappings":"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","names":["path","manifest"]}
|
|
1
|
+
{"version":3,"sources":["../src/nextjs-adapter.ts"],"sourcesContent":["import type { NextAdapter } from 'next';\nimport { access, mkdir, realpath, stat, writeFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { NormalizedImagePolicy } from './image-policy';\nimport type {\n GigadriveNextBuildManifestV1,\n GigadriveNextBuildManifestV2Export,\n GigadriveNextBuildManifestV2Standalone,\n GigadriveNextPrerenderOutput,\n GigadriveNextServerDescriptor,\n GigadriveNextStaticAssetPrefix,\n JsonValue,\n} from './nextjs-manifest';\n\ntype BuildCompleteContext = Parameters<NonNullable<NextAdapter['onBuildComplete']>>[0];\ntype NextRouteOutput =\n | BuildCompleteContext['outputs']['pages'][number]\n | BuildCompleteContext['outputs']['pagesApi'][number]\n | BuildCompleteContext['outputs']['appPages'][number]\n | BuildCompleteContext['outputs']['appRoutes'][number]\n | NonNullable<BuildCompleteContext['outputs']['middleware']>;\ntype NextPrerenderOutput = BuildCompleteContext['outputs']['prerenders'][number];\n\nconst PRODUCTION_BUILD_PHASE = 'phase-production-build';\nconst runtimeDirectory = typeof __dirname === 'string' ? __dirname : path.dirname(fileURLToPath(import.meta.url));\n\nconst runtimeModulePath = (environmentName: string, fileName: string): string =>\n process.env[environmentName] ?? path.join(runtimeDirectory, fileName);\n\nconst CACHE_HANDLER_PATH = () => runtimeModulePath('GIGADRIVE_NEXT_CACHE_HANDLER_PATH', 'nextjs-cache-handler.js');\nconst CACHE_COMPONENTS_HANDLER_PATH = () =>\n runtimeModulePath('GIGADRIVE_NEXT_CACHE_COMPONENTS_HANDLER_PATH', 'nextjs-cache-components-handler.js');\nconst IMAGE_LOADER_PATH = () => runtimeModulePath('GIGADRIVE_NEXT_IMAGE_LOADER_PATH', 'nextjs-image-loader.js');\n\nconst toJsonValue = (value: unknown): JsonValue => {\n const serialized = JSON.stringify(value);\n return serialized === undefined ? null : (JSON.parse(serialized) as JsonValue);\n};\n\n/**\n * Next 16.2 introduced the adapter hooks (`modifyConfig` + `onBuildComplete`) and\n * the `cacheHandler`/`cacheHandlers`/`cacheComponents` config fields we inject.\n * Earlier releases keep the legacy standalone-only behavior with no injection.\n */\nconst supportsManagedRuntime = (nextVersion: string | undefined): boolean => {\n if (!nextVersion) return false;\n const [majorPart, minorPart] = nextVersion.split('.');\n const major = Number.parseInt(majorPart ?? '', 10);\n const minor = Number.parseInt(minorPart ?? '', 10);\n return Number.isFinite(major) && Number.isFinite(minor) && (major > 16 || (major === 16 && minor >= 2));\n};\n\n/**\n * Highest Next major validated to allow `output: 'standalone'` together with an\n * adapter. Next's own build source warns the combination \"might not be allowed\"\n * in a future release. We always emit `output: 'standalone'` on the managed path\n * (there is no per-route fallback to degrade to), so if a future major forbids\n * it the build fails loudly at `next build` rather than silently misdeploying.\n * The network canary drift test tracks releases past this bound.\n */\nconst MANAGED_STANDALONE_VALIDATED_MAX_MAJOR = 16;\n\nconst toPortableRelativePath = (from: string, to: string, allowCurrentDirectory = false): string => {\n const resolvedFrom = path.resolve(from);\n const resolvedTo = path.resolve(path.isAbsolute(to) ? to : path.join(from, to));\n const relativePath = path.relative(resolvedFrom, resolvedTo).replaceAll(path.sep, '/');\n const normalized = relativePath === '' ? '.' : relativePath;\n if (\n (!allowCurrentDirectory && normalized === '.') ||\n normalized.startsWith('/') ||\n /^[A-Za-z]:/.test(normalized) ||\n normalized.split('/').some((segment) => segment === '..')\n ) {\n throw new Error(`Next.js adapter output is outside the repository root: ${to}`);\n }\n return normalized;\n};\n\nasync function resolveReadablePath(repoRoot: string, filePath: string) {\n const absolutePath = path.resolve(path.isAbsolute(filePath) ? filePath : path.join(repoRoot, filePath));\n const portablePath = toPortableRelativePath(repoRoot, absolutePath);\n await access(absolutePath);\n // Validate the symlink-resolved location as well; the call throws when the\n // real path escapes the repository root.\n const resolvedPath = await realpath(absolutePath);\n void toPortableRelativePath(repoRoot, resolvedPath);\n const fileStat = await stat(absolutePath);\n return { portablePath, fileStat };\n}\n\nasync function requireReadableFile(repoRoot: string, filePath: string): Promise<string> {\n const { portablePath, fileStat } = await resolveReadablePath(repoRoot, filePath);\n if (!fileStat.isFile()) throw new Error(`Next.js adapter output is not a readable file: ${filePath}`);\n return portablePath;\n}\n\nconst serializePrerenderOutput = async (\n repoRoot: string,\n output: NextPrerenderOutput\n): Promise<GigadriveNextPrerenderOutput> => {\n const { bypassFor, ...prerenderConfig } = output.config;\n return {\n id: output.id,\n type: 'PRERENDER',\n pathname: output.pathname,\n parentOutputId: output.parentOutputId,\n groupId: output.groupId,\n ...(output.pprChain ? { pprChain: output.pprChain } : {}),\n ...(output.parentFallbackMode !== undefined ? { parentFallbackMode: toJsonValue(output.parentFallbackMode) } : {}),\n ...(output.fallback\n ? {\n fallback: {\n ...(output.fallback.filePath\n ? { filePath: await requireReadableFile(repoRoot, output.fallback.filePath) }\n : {}),\n ...(output.fallback.initialStatus !== undefined ? { initialStatus: output.fallback.initialStatus } : {}),\n ...(output.fallback.initialHeaders ? { initialHeaders: output.fallback.initialHeaders } : {}),\n ...(output.fallback.initialExpiration !== undefined\n ? { initialExpiration: output.fallback.initialExpiration }\n : {}),\n ...(output.fallback.initialRevalidate !== undefined\n ? { initialRevalidate: output.fallback.initialRevalidate }\n : {}),\n ...(output.fallback.postponedState !== undefined ? { postponedState: output.fallback.postponedState } : {}),\n },\n }\n : {}),\n config: {\n ...prerenderConfig,\n ...(bypassFor ? { bypassFor: toJsonValue(bypassFor) as JsonValue[] } : {}),\n },\n };\n};\n\n/**\n * Collapses per-route runtime config onto the one standalone server. `maxDuration`\n * becomes the max across routes (one function honors one limit); `env` is the union\n * of every route's declared env (the single server runs them all in-process).\n */\nconst aggregateServerDescriptor = (outputs: NextRouteOutput[]): GigadriveNextServerDescriptor => {\n let maxDuration: number | undefined;\n const env: Record<string, string> = {};\n for (const output of outputs) {\n if (output.config.maxDuration !== undefined) {\n maxDuration = Math.max(maxDuration ?? 0, output.config.maxDuration);\n }\n if (output.config.env) Object.assign(env, output.config.env);\n }\n return {\n ...(maxDuration !== undefined ? { maxDuration } : {}),\n ...(Object.keys(env).length > 0 ? { env } : {}),\n };\n};\n\ntype CollectBuildTracesModule = {\n collectBuildTraces: (options: {\n dir: string;\n config: BuildCompleteContext['config'];\n distDir: string;\n edgeRuntimeRoutes: Record<string, never>;\n staticPages: string[];\n outputFileTracingRoot: string;\n }) => Promise<void>;\n};\n\n/**\n * Next 16.3 stopped emitting the aggregated `next-server.js.nft.json` /\n * `next-minimal-server.js.nft.json` traces from Turbopack builds whenever an\n * adapter is configured, yet `next build` still runs the `output: 'standalone'`\n * writer after `onBuildComplete` — and that writer reads exactly this file, so\n * the build dies with ENOENT. Next 16.2 and all webpack builds still emit the\n * file, making this a no-op there. When the file is missing, regenerate both\n * aggregate traces with Next's own `collectBuildTraces` (the module the webpack\n * pipeline runs); without `buildTraceContext` it only writes the two aggregate\n * trace files and leaves Turbopack's per-entry traces untouched.\n */\nasync function ensureStandaloneServerTraces(\n projectDir: string,\n repoRoot: string,\n distDir: string,\n config: BuildCompleteContext['config']\n): Promise<void> {\n const aggregateTracePath = path.join(distDir, 'next-server.js.nft.json');\n try {\n await access(aggregateTracePath);\n return;\n } catch {\n // Missing — Next will crash in its standalone writer unless we regenerate it.\n }\n let collectBuildTracesModule: CollectBuildTracesModule;\n try {\n const projectRequire = createRequire(path.join(projectDir, 'package.json'));\n collectBuildTracesModule = projectRequire('next/dist/build/collect-build-traces') as CollectBuildTracesModule;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Next.js did not emit ${aggregateTracePath} and the Gigadrive adapter could not load ` +\n `next/dist/build/collect-build-traces from the project to regenerate it: ${message}`\n );\n }\n try {\n await collectBuildTracesModule.collectBuildTraces({\n dir: projectDir,\n config,\n distDir,\n edgeRuntimeRoutes: {},\n staticPages: [],\n outputFileTracingRoot: (config as { outputFileTracingRoot?: string }).outputFileTracingRoot ?? repoRoot,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Regenerating the Next.js standalone server traces (${aggregateTracePath}) failed: ${message}`);\n }\n}\n\nconst normalizeImages = (config: BuildCompleteContext['config']): NormalizedImagePolicy | undefined => {\n if (config.images.unoptimized) return undefined;\n return {\n localPatterns: config.images.localPatterns ?? [{ pathname: '/**' }],\n remotePatterns: config.images.remotePatterns.map((pattern) => {\n if (pattern instanceof URL) {\n return {\n protocol: pattern.protocol === 'http:' ? ('http' as const) : ('https' as const),\n hostname: pattern.hostname,\n port: pattern.port,\n pathname: pattern.pathname,\n search: pattern.search,\n };\n }\n return { ...pattern };\n }),\n widths: [...new Set([...config.images.deviceSizes, ...config.images.imageSizes])].sort((a, b) => a - b),\n heights: [],\n qualities: config.images.qualities ?? [75],\n formats: config.images.formats,\n minimumCacheTTL: config.images.minimumCacheTTL,\n dangerouslyAllowSVG: config.images.dangerouslyAllowSVG,\n contentSecurityPolicy: config.images.contentSecurityPolicy,\n contentDispositionType: config.images.contentDispositionType,\n maximumRedirects: config.images.maximumRedirects,\n maximumResponseBody: config.images.maximumResponseBody,\n variants: {},\n };\n};\n\n/**\n * Next.js deployment adapter used automatically by Gigadrive Network build workers.\n *\n * Next 16.2 and newer run the entire deployment as a single `output: 'standalone'`\n * server (one function per deployment) while the injected cache handlers, image\n * loader, and this hook's `onBuildComplete` metadata keep ISR, PPR, `use cache`,\n * and image optimization working through the platform's durable runtime-cache and\n * edge image services. Older releases retain the legacy standalone behavior without\n * the managed-runtime injections.\n */\nconst gigadriveNextAdapter: NextAdapter = {\n name: 'Gigadrive Network',\n\n modifyConfig(config, { phase, nextVersion }) {\n if (phase !== PRODUCTION_BUILD_PHASE) return config;\n\n const deploymentId = config.deploymentId ?? process.env.GIGADRIVE_DEPLOYMENT_ID;\n if (!supportsManagedRuntime(nextVersion)) {\n return {\n ...config,\n ...(deploymentId ? { deploymentId } : {}),\n output: config.output === 'export' ? 'export' : 'standalone',\n };\n }\n if (config.output === 'export') {\n return { ...config, ...(deploymentId ? { deploymentId } : {}) };\n }\n\n const injectCacheHandler = config.cacheHandler === undefined;\n const injectCacheComponentHandlers = config.cacheHandlers === undefined;\n const images = config.images;\n const injectImageLoader =\n images !== undefined && images.unoptimized !== true && images.loader === 'default' && !images.loaderFile;\n\n return {\n ...config,\n ...(deploymentId ? { deploymentId } : {}),\n // Run the whole deployment as one standalone Next server rather than a\n // serverless function per route. `onBuildComplete` still fires under\n // standalone (Next >= 16.2), and the standalone server natively honors the\n // injected cache handlers and resumes PPR from its incremental cache, so\n // ISR/PPR/`use cache` stay durable via the remote runtime-cache service.\n // Validated on Next 16.2.x (see MANAGED_STANDALONE_VALIDATED_MAX_MAJOR);\n // a future major that forbids adapter + standalone fails loudly at build.\n output: 'standalone',\n ...(injectCacheHandler ? { cacheHandler: CACHE_HANDLER_PATH() } : {}),\n ...(injectCacheComponentHandlers\n ? {\n cacheHandlers: {\n default: CACHE_COMPONENTS_HANDLER_PATH(),\n remote: CACHE_COMPONENTS_HANDLER_PATH(),\n },\n }\n : {}),\n ...(injectCacheHandler || injectCacheComponentHandlers ? { cacheMaxMemorySize: 0 } : {}),\n ...(injectImageLoader\n ? {\n images: {\n ...images,\n loader: 'custom',\n loaderFile: IMAGE_LOADER_PATH(),\n },\n }\n : {}),\n };\n },\n\n async onBuildComplete({ projectDir, repoRoot, distDir, config, nextVersion, buildId, routing, outputs }) {\n const metadataDirectory = path.join(projectDir, '.gigadrive');\n await mkdir(metadataDirectory, { recursive: true });\n const manifestPath = path.join(metadataDirectory, 'nextjs.json');\n const writeManifest = (manifest: unknown) =>\n writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8');\n\n if (!supportsManagedRuntime(nextVersion)) {\n const manifest: GigadriveNextBuildManifestV1 = {\n version: 1,\n output: config.output === 'export' ? 'export' : 'standalone',\n distDir: toPortableRelativePath(projectDir, distDir),\n repoRootToProject: toPortableRelativePath(repoRoot, projectDir, true),\n nextVersion,\n buildId,\n };\n await writeManifest(manifest);\n return;\n }\n\n const portableDistDir = toPortableRelativePath(projectDir, distDir);\n const repoRootToProject = toPortableRelativePath(repoRoot, projectDir, true);\n\n if (config.output === 'export') {\n const manifest: GigadriveNextBuildManifestV2Export = {\n version: 2,\n mode: 'export',\n distDir: portableDistDir,\n repoRootToProject,\n nextVersion,\n buildId,\n };\n await writeManifest(manifest);\n return;\n }\n\n if (config.output === 'standalone') {\n await ensureStandaloneServerTraces(projectDir, repoRoot, distDir, config);\n }\n\n const prerenders = await Promise.all(\n outputs.prerenders.map((output) => serializePrerenderOutput(repoRoot, output))\n );\n const server = aggregateServerDescriptor([\n ...outputs.pages,\n ...outputs.pagesApi,\n ...outputs.appPages,\n ...outputs.appRoutes,\n ...(outputs.middleware ? [outputs.middleware] : []),\n ]);\n const images = normalizeImages(config);\n // `.next/static` is thousands of content-hashed, immutable chunks. Register\n // the whole subtree as one edge-served prefix instead of enumerating files.\n const staticAssets: GigadriveNextStaticAssetPrefix[] = [\n { sourceDir: `${portableDistDir}/static`, urlPrefix: '_next/static', immutable: true },\n ];\n\n const manifest: GigadriveNextBuildManifestV2Standalone = {\n version: 2,\n mode: 'standalone-v2',\n distDir: portableDistDir,\n repoRootToProject,\n nextVersion,\n buildId,\n server,\n config: {\n basePath: config.basePath,\n trailingSlash: config.trailingSlash,\n cacheComponents: config.cacheComponents,\n ...(config.i18n ? { i18n: toJsonValue(config.i18n) } : {}),\n ...(images ? { images } : {}),\n },\n routing: {\n beforeMiddleware: toJsonValue(routing.beforeMiddleware) as JsonValue[],\n beforeFiles: toJsonValue(routing.beforeFiles) as JsonValue[],\n afterFiles: toJsonValue(routing.afterFiles) as JsonValue[],\n dynamicRoutes: toJsonValue(routing.dynamicRoutes) as JsonValue[],\n onMatch: toJsonValue(routing.onMatch) as JsonValue[],\n fallback: toJsonValue(routing.fallback) as JsonValue[],\n shouldNormalizeNextData: routing.shouldNormalizeNextData,\n rsc: toJsonValue(routing.rsc),\n },\n outputs: { prerenders, staticAssets },\n };\n await writeManifest(manifest);\n },\n};\n\nexport { MANAGED_STANDALONE_VALIDATED_MAX_MAJOR };\nexport default gigadriveNextAdapter;\n"],"mappings":"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","names":["path","manifest"]}
|
package/dist/nextjs-adapter.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/nextjs-adapter.ts
|
|
2
2
|
import { access, mkdir, realpath, stat, writeFile } from "fs/promises";
|
|
3
|
+
import { createRequire } from "module";
|
|
3
4
|
import path from "path";
|
|
4
5
|
import { fileURLToPath } from "url";
|
|
5
6
|
var PRODUCTION_BUILD_PHASE = "phase-production-build";
|
|
@@ -84,6 +85,37 @@ var aggregateServerDescriptor = (outputs) => {
|
|
|
84
85
|
...Object.keys(env).length > 0 ? { env } : {}
|
|
85
86
|
};
|
|
86
87
|
};
|
|
88
|
+
async function ensureStandaloneServerTraces(projectDir, repoRoot, distDir, config) {
|
|
89
|
+
const aggregateTracePath = path.join(distDir, "next-server.js.nft.json");
|
|
90
|
+
try {
|
|
91
|
+
await access(aggregateTracePath);
|
|
92
|
+
return;
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
let collectBuildTracesModule;
|
|
96
|
+
try {
|
|
97
|
+
const projectRequire = createRequire(path.join(projectDir, "package.json"));
|
|
98
|
+
collectBuildTracesModule = projectRequire("next/dist/build/collect-build-traces");
|
|
99
|
+
} catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Next.js did not emit ${aggregateTracePath} and the Gigadrive adapter could not load next/dist/build/collect-build-traces from the project to regenerate it: ${message}`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
await collectBuildTracesModule.collectBuildTraces({
|
|
107
|
+
dir: projectDir,
|
|
108
|
+
config,
|
|
109
|
+
distDir,
|
|
110
|
+
edgeRuntimeRoutes: {},
|
|
111
|
+
staticPages: [],
|
|
112
|
+
outputFileTracingRoot: config.outputFileTracingRoot ?? repoRoot
|
|
113
|
+
});
|
|
114
|
+
} catch (error) {
|
|
115
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
116
|
+
throw new Error(`Regenerating the Next.js standalone server traces (${aggregateTracePath}) failed: ${message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
87
119
|
var normalizeImages = (config) => {
|
|
88
120
|
if (config.images.unoptimized) return void 0;
|
|
89
121
|
return {
|
|
@@ -192,6 +224,9 @@ var gigadriveNextAdapter = {
|
|
|
192
224
|
await writeManifest(manifest2);
|
|
193
225
|
return;
|
|
194
226
|
}
|
|
227
|
+
if (config.output === "standalone") {
|
|
228
|
+
await ensureStandaloneServerTraces(projectDir, repoRoot, distDir, config);
|
|
229
|
+
}
|
|
195
230
|
const prerenders = await Promise.all(
|
|
196
231
|
outputs.prerenders.map((output) => serializePrerenderOutput(repoRoot, output))
|
|
197
232
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nextjs-adapter.ts"],"sourcesContent":["import type { NextAdapter } from 'next';\nimport { access, mkdir, realpath, stat, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { NormalizedImagePolicy } from './image-policy';\nimport type {\n GigadriveNextBuildManifestV1,\n GigadriveNextBuildManifestV2Export,\n GigadriveNextBuildManifestV2Standalone,\n GigadriveNextPrerenderOutput,\n GigadriveNextServerDescriptor,\n GigadriveNextStaticAssetPrefix,\n JsonValue,\n} from './nextjs-manifest';\n\ntype BuildCompleteContext = Parameters<NonNullable<NextAdapter['onBuildComplete']>>[0];\ntype NextRouteOutput =\n | BuildCompleteContext['outputs']['pages'][number]\n | BuildCompleteContext['outputs']['pagesApi'][number]\n | BuildCompleteContext['outputs']['appPages'][number]\n | BuildCompleteContext['outputs']['appRoutes'][number]\n | NonNullable<BuildCompleteContext['outputs']['middleware']>;\ntype NextPrerenderOutput = BuildCompleteContext['outputs']['prerenders'][number];\n\nconst PRODUCTION_BUILD_PHASE = 'phase-production-build';\nconst runtimeDirectory = typeof __dirname === 'string' ? __dirname : path.dirname(fileURLToPath(import.meta.url));\n\nconst runtimeModulePath = (environmentName: string, fileName: string): string =>\n process.env[environmentName] ?? path.join(runtimeDirectory, fileName);\n\nconst CACHE_HANDLER_PATH = () => runtimeModulePath('GIGADRIVE_NEXT_CACHE_HANDLER_PATH', 'nextjs-cache-handler.js');\nconst CACHE_COMPONENTS_HANDLER_PATH = () =>\n runtimeModulePath('GIGADRIVE_NEXT_CACHE_COMPONENTS_HANDLER_PATH', 'nextjs-cache-components-handler.js');\nconst IMAGE_LOADER_PATH = () => runtimeModulePath('GIGADRIVE_NEXT_IMAGE_LOADER_PATH', 'nextjs-image-loader.js');\n\nconst toJsonValue = (value: unknown): JsonValue => {\n const serialized = JSON.stringify(value);\n return serialized === undefined ? null : (JSON.parse(serialized) as JsonValue);\n};\n\n/**\n * Next 16.2 introduced the adapter hooks (`modifyConfig` + `onBuildComplete`) and\n * the `cacheHandler`/`cacheHandlers`/`cacheComponents` config fields we inject.\n * Earlier releases keep the legacy standalone-only behavior with no injection.\n */\nconst supportsManagedRuntime = (nextVersion: string | undefined): boolean => {\n if (!nextVersion) return false;\n const [majorPart, minorPart] = nextVersion.split('.');\n const major = Number.parseInt(majorPart ?? '', 10);\n const minor = Number.parseInt(minorPart ?? '', 10);\n return Number.isFinite(major) && Number.isFinite(minor) && (major > 16 || (major === 16 && minor >= 2));\n};\n\n/**\n * Highest Next major validated to allow `output: 'standalone'` together with an\n * adapter. Next's own build source warns the combination \"might not be allowed\"\n * in a future release. We always emit `output: 'standalone'` on the managed path\n * (there is no per-route fallback to degrade to), so if a future major forbids\n * it the build fails loudly at `next build` rather than silently misdeploying.\n * The network canary drift test tracks releases past this bound.\n */\nconst MANAGED_STANDALONE_VALIDATED_MAX_MAJOR = 16;\n\nconst toPortableRelativePath = (from: string, to: string, allowCurrentDirectory = false): string => {\n const resolvedFrom = path.resolve(from);\n const resolvedTo = path.resolve(path.isAbsolute(to) ? to : path.join(from, to));\n const relativePath = path.relative(resolvedFrom, resolvedTo).replaceAll(path.sep, '/');\n const normalized = relativePath === '' ? '.' : relativePath;\n if (\n (!allowCurrentDirectory && normalized === '.') ||\n normalized.startsWith('/') ||\n /^[A-Za-z]:/.test(normalized) ||\n normalized.split('/').some((segment) => segment === '..')\n ) {\n throw new Error(`Next.js adapter output is outside the repository root: ${to}`);\n }\n return normalized;\n};\n\nasync function resolveReadablePath(repoRoot: string, filePath: string) {\n const absolutePath = path.resolve(path.isAbsolute(filePath) ? filePath : path.join(repoRoot, filePath));\n const portablePath = toPortableRelativePath(repoRoot, absolutePath);\n await access(absolutePath);\n // Validate the symlink-resolved location as well; the call throws when the\n // real path escapes the repository root.\n const resolvedPath = await realpath(absolutePath);\n void toPortableRelativePath(repoRoot, resolvedPath);\n const fileStat = await stat(absolutePath);\n return { portablePath, fileStat };\n}\n\nasync function requireReadableFile(repoRoot: string, filePath: string): Promise<string> {\n const { portablePath, fileStat } = await resolveReadablePath(repoRoot, filePath);\n if (!fileStat.isFile()) throw new Error(`Next.js adapter output is not a readable file: ${filePath}`);\n return portablePath;\n}\n\nconst serializePrerenderOutput = async (\n repoRoot: string,\n output: NextPrerenderOutput\n): Promise<GigadriveNextPrerenderOutput> => {\n const { bypassFor, ...prerenderConfig } = output.config;\n return {\n id: output.id,\n type: 'PRERENDER',\n pathname: output.pathname,\n parentOutputId: output.parentOutputId,\n groupId: output.groupId,\n ...(output.pprChain ? { pprChain: output.pprChain } : {}),\n ...(output.parentFallbackMode !== undefined ? { parentFallbackMode: toJsonValue(output.parentFallbackMode) } : {}),\n ...(output.fallback\n ? {\n fallback: {\n ...(output.fallback.filePath\n ? { filePath: await requireReadableFile(repoRoot, output.fallback.filePath) }\n : {}),\n ...(output.fallback.initialStatus !== undefined ? { initialStatus: output.fallback.initialStatus } : {}),\n ...(output.fallback.initialHeaders ? { initialHeaders: output.fallback.initialHeaders } : {}),\n ...(output.fallback.initialExpiration !== undefined\n ? { initialExpiration: output.fallback.initialExpiration }\n : {}),\n ...(output.fallback.initialRevalidate !== undefined\n ? { initialRevalidate: output.fallback.initialRevalidate }\n : {}),\n ...(output.fallback.postponedState !== undefined ? { postponedState: output.fallback.postponedState } : {}),\n },\n }\n : {}),\n config: {\n ...prerenderConfig,\n ...(bypassFor ? { bypassFor: toJsonValue(bypassFor) as JsonValue[] } : {}),\n },\n };\n};\n\n/**\n * Collapses per-route runtime config onto the one standalone server. `maxDuration`\n * becomes the max across routes (one function honors one limit); `env` is the union\n * of every route's declared env (the single server runs them all in-process).\n */\nconst aggregateServerDescriptor = (outputs: NextRouteOutput[]): GigadriveNextServerDescriptor => {\n let maxDuration: number | undefined;\n const env: Record<string, string> = {};\n for (const output of outputs) {\n if (output.config.maxDuration !== undefined) {\n maxDuration = Math.max(maxDuration ?? 0, output.config.maxDuration);\n }\n if (output.config.env) Object.assign(env, output.config.env);\n }\n return {\n ...(maxDuration !== undefined ? { maxDuration } : {}),\n ...(Object.keys(env).length > 0 ? { env } : {}),\n };\n};\n\nconst normalizeImages = (config: BuildCompleteContext['config']): NormalizedImagePolicy | undefined => {\n if (config.images.unoptimized) return undefined;\n return {\n localPatterns: config.images.localPatterns ?? [{ pathname: '/**' }],\n remotePatterns: config.images.remotePatterns.map((pattern) => {\n if (pattern instanceof URL) {\n return {\n protocol: pattern.protocol === 'http:' ? ('http' as const) : ('https' as const),\n hostname: pattern.hostname,\n port: pattern.port,\n pathname: pattern.pathname,\n search: pattern.search,\n };\n }\n return { ...pattern };\n }),\n widths: [...new Set([...config.images.deviceSizes, ...config.images.imageSizes])].sort((a, b) => a - b),\n heights: [],\n qualities: config.images.qualities ?? [75],\n formats: config.images.formats,\n minimumCacheTTL: config.images.minimumCacheTTL,\n dangerouslyAllowSVG: config.images.dangerouslyAllowSVG,\n contentSecurityPolicy: config.images.contentSecurityPolicy,\n contentDispositionType: config.images.contentDispositionType,\n maximumRedirects: config.images.maximumRedirects,\n maximumResponseBody: config.images.maximumResponseBody,\n variants: {},\n };\n};\n\n/**\n * Next.js deployment adapter used automatically by Gigadrive Network build workers.\n *\n * Next 16.2 and newer run the entire deployment as a single `output: 'standalone'`\n * server (one function per deployment) while the injected cache handlers, image\n * loader, and this hook's `onBuildComplete` metadata keep ISR, PPR, `use cache`,\n * and image optimization working through the platform's durable runtime-cache and\n * edge image services. Older releases retain the legacy standalone behavior without\n * the managed-runtime injections.\n */\nconst gigadriveNextAdapter: NextAdapter = {\n name: 'Gigadrive Network',\n\n modifyConfig(config, { phase, nextVersion }) {\n if (phase !== PRODUCTION_BUILD_PHASE) return config;\n\n const deploymentId = config.deploymentId ?? process.env.GIGADRIVE_DEPLOYMENT_ID;\n if (!supportsManagedRuntime(nextVersion)) {\n return {\n ...config,\n ...(deploymentId ? { deploymentId } : {}),\n output: config.output === 'export' ? 'export' : 'standalone',\n };\n }\n if (config.output === 'export') {\n return { ...config, ...(deploymentId ? { deploymentId } : {}) };\n }\n\n const injectCacheHandler = config.cacheHandler === undefined;\n const injectCacheComponentHandlers = config.cacheHandlers === undefined;\n const images = config.images;\n const injectImageLoader =\n images !== undefined && images.unoptimized !== true && images.loader === 'default' && !images.loaderFile;\n\n return {\n ...config,\n ...(deploymentId ? { deploymentId } : {}),\n // Run the whole deployment as one standalone Next server rather than a\n // serverless function per route. `onBuildComplete` still fires under\n // standalone (Next >= 16.2), and the standalone server natively honors the\n // injected cache handlers and resumes PPR from its incremental cache, so\n // ISR/PPR/`use cache` stay durable via the remote runtime-cache service.\n // Validated on Next 16.2.x (see MANAGED_STANDALONE_VALIDATED_MAX_MAJOR);\n // a future major that forbids adapter + standalone fails loudly at build.\n output: 'standalone',\n ...(injectCacheHandler ? { cacheHandler: CACHE_HANDLER_PATH() } : {}),\n ...(injectCacheComponentHandlers\n ? {\n cacheHandlers: {\n default: CACHE_COMPONENTS_HANDLER_PATH(),\n remote: CACHE_COMPONENTS_HANDLER_PATH(),\n },\n }\n : {}),\n ...(injectCacheHandler || injectCacheComponentHandlers ? { cacheMaxMemorySize: 0 } : {}),\n ...(injectImageLoader\n ? {\n images: {\n ...images,\n loader: 'custom',\n loaderFile: IMAGE_LOADER_PATH(),\n },\n }\n : {}),\n };\n },\n\n async onBuildComplete({ projectDir, repoRoot, distDir, config, nextVersion, buildId, routing, outputs }) {\n const metadataDirectory = path.join(projectDir, '.gigadrive');\n await mkdir(metadataDirectory, { recursive: true });\n const manifestPath = path.join(metadataDirectory, 'nextjs.json');\n const writeManifest = (manifest: unknown) =>\n writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8');\n\n if (!supportsManagedRuntime(nextVersion)) {\n const manifest: GigadriveNextBuildManifestV1 = {\n version: 1,\n output: config.output === 'export' ? 'export' : 'standalone',\n distDir: toPortableRelativePath(projectDir, distDir),\n repoRootToProject: toPortableRelativePath(repoRoot, projectDir, true),\n nextVersion,\n buildId,\n };\n await writeManifest(manifest);\n return;\n }\n\n const portableDistDir = toPortableRelativePath(projectDir, distDir);\n const repoRootToProject = toPortableRelativePath(repoRoot, projectDir, true);\n\n if (config.output === 'export') {\n const manifest: GigadriveNextBuildManifestV2Export = {\n version: 2,\n mode: 'export',\n distDir: portableDistDir,\n repoRootToProject,\n nextVersion,\n buildId,\n };\n await writeManifest(manifest);\n return;\n }\n\n const prerenders = await Promise.all(\n outputs.prerenders.map((output) => serializePrerenderOutput(repoRoot, output))\n );\n const server = aggregateServerDescriptor([\n ...outputs.pages,\n ...outputs.pagesApi,\n ...outputs.appPages,\n ...outputs.appRoutes,\n ...(outputs.middleware ? [outputs.middleware] : []),\n ]);\n const images = normalizeImages(config);\n // `.next/static` is thousands of content-hashed, immutable chunks. Register\n // the whole subtree as one edge-served prefix instead of enumerating files.\n const staticAssets: GigadriveNextStaticAssetPrefix[] = [\n { sourceDir: `${portableDistDir}/static`, urlPrefix: '_next/static', immutable: true },\n ];\n\n const manifest: GigadriveNextBuildManifestV2Standalone = {\n version: 2,\n mode: 'standalone-v2',\n distDir: portableDistDir,\n repoRootToProject,\n nextVersion,\n buildId,\n server,\n config: {\n basePath: config.basePath,\n trailingSlash: config.trailingSlash,\n cacheComponents: config.cacheComponents,\n ...(config.i18n ? { i18n: toJsonValue(config.i18n) } : {}),\n ...(images ? { images } : {}),\n },\n routing: {\n beforeMiddleware: toJsonValue(routing.beforeMiddleware) as JsonValue[],\n beforeFiles: toJsonValue(routing.beforeFiles) as JsonValue[],\n afterFiles: toJsonValue(routing.afterFiles) as JsonValue[],\n dynamicRoutes: toJsonValue(routing.dynamicRoutes) as JsonValue[],\n onMatch: toJsonValue(routing.onMatch) as JsonValue[],\n fallback: toJsonValue(routing.fallback) as JsonValue[],\n shouldNormalizeNextData: routing.shouldNormalizeNextData,\n rsc: toJsonValue(routing.rsc),\n },\n outputs: { prerenders, staticAssets },\n };\n await writeManifest(manifest);\n },\n};\n\nexport { MANAGED_STANDALONE_VALIDATED_MAX_MAJOR };\nexport default gigadriveNextAdapter;\n"],"mappings":"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","names":["manifest"]}
|
|
1
|
+
{"version":3,"sources":["../src/nextjs-adapter.ts"],"sourcesContent":["import type { NextAdapter } from 'next';\nimport { access, mkdir, realpath, stat, writeFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { NormalizedImagePolicy } from './image-policy';\nimport type {\n GigadriveNextBuildManifestV1,\n GigadriveNextBuildManifestV2Export,\n GigadriveNextBuildManifestV2Standalone,\n GigadriveNextPrerenderOutput,\n GigadriveNextServerDescriptor,\n GigadriveNextStaticAssetPrefix,\n JsonValue,\n} from './nextjs-manifest';\n\ntype BuildCompleteContext = Parameters<NonNullable<NextAdapter['onBuildComplete']>>[0];\ntype NextRouteOutput =\n | BuildCompleteContext['outputs']['pages'][number]\n | BuildCompleteContext['outputs']['pagesApi'][number]\n | BuildCompleteContext['outputs']['appPages'][number]\n | BuildCompleteContext['outputs']['appRoutes'][number]\n | NonNullable<BuildCompleteContext['outputs']['middleware']>;\ntype NextPrerenderOutput = BuildCompleteContext['outputs']['prerenders'][number];\n\nconst PRODUCTION_BUILD_PHASE = 'phase-production-build';\nconst runtimeDirectory = typeof __dirname === 'string' ? __dirname : path.dirname(fileURLToPath(import.meta.url));\n\nconst runtimeModulePath = (environmentName: string, fileName: string): string =>\n process.env[environmentName] ?? path.join(runtimeDirectory, fileName);\n\nconst CACHE_HANDLER_PATH = () => runtimeModulePath('GIGADRIVE_NEXT_CACHE_HANDLER_PATH', 'nextjs-cache-handler.js');\nconst CACHE_COMPONENTS_HANDLER_PATH = () =>\n runtimeModulePath('GIGADRIVE_NEXT_CACHE_COMPONENTS_HANDLER_PATH', 'nextjs-cache-components-handler.js');\nconst IMAGE_LOADER_PATH = () => runtimeModulePath('GIGADRIVE_NEXT_IMAGE_LOADER_PATH', 'nextjs-image-loader.js');\n\nconst toJsonValue = (value: unknown): JsonValue => {\n const serialized = JSON.stringify(value);\n return serialized === undefined ? null : (JSON.parse(serialized) as JsonValue);\n};\n\n/**\n * Next 16.2 introduced the adapter hooks (`modifyConfig` + `onBuildComplete`) and\n * the `cacheHandler`/`cacheHandlers`/`cacheComponents` config fields we inject.\n * Earlier releases keep the legacy standalone-only behavior with no injection.\n */\nconst supportsManagedRuntime = (nextVersion: string | undefined): boolean => {\n if (!nextVersion) return false;\n const [majorPart, minorPart] = nextVersion.split('.');\n const major = Number.parseInt(majorPart ?? '', 10);\n const minor = Number.parseInt(minorPart ?? '', 10);\n return Number.isFinite(major) && Number.isFinite(minor) && (major > 16 || (major === 16 && minor >= 2));\n};\n\n/**\n * Highest Next major validated to allow `output: 'standalone'` together with an\n * adapter. Next's own build source warns the combination \"might not be allowed\"\n * in a future release. We always emit `output: 'standalone'` on the managed path\n * (there is no per-route fallback to degrade to), so if a future major forbids\n * it the build fails loudly at `next build` rather than silently misdeploying.\n * The network canary drift test tracks releases past this bound.\n */\nconst MANAGED_STANDALONE_VALIDATED_MAX_MAJOR = 16;\n\nconst toPortableRelativePath = (from: string, to: string, allowCurrentDirectory = false): string => {\n const resolvedFrom = path.resolve(from);\n const resolvedTo = path.resolve(path.isAbsolute(to) ? to : path.join(from, to));\n const relativePath = path.relative(resolvedFrom, resolvedTo).replaceAll(path.sep, '/');\n const normalized = relativePath === '' ? '.' : relativePath;\n if (\n (!allowCurrentDirectory && normalized === '.') ||\n normalized.startsWith('/') ||\n /^[A-Za-z]:/.test(normalized) ||\n normalized.split('/').some((segment) => segment === '..')\n ) {\n throw new Error(`Next.js adapter output is outside the repository root: ${to}`);\n }\n return normalized;\n};\n\nasync function resolveReadablePath(repoRoot: string, filePath: string) {\n const absolutePath = path.resolve(path.isAbsolute(filePath) ? filePath : path.join(repoRoot, filePath));\n const portablePath = toPortableRelativePath(repoRoot, absolutePath);\n await access(absolutePath);\n // Validate the symlink-resolved location as well; the call throws when the\n // real path escapes the repository root.\n const resolvedPath = await realpath(absolutePath);\n void toPortableRelativePath(repoRoot, resolvedPath);\n const fileStat = await stat(absolutePath);\n return { portablePath, fileStat };\n}\n\nasync function requireReadableFile(repoRoot: string, filePath: string): Promise<string> {\n const { portablePath, fileStat } = await resolveReadablePath(repoRoot, filePath);\n if (!fileStat.isFile()) throw new Error(`Next.js adapter output is not a readable file: ${filePath}`);\n return portablePath;\n}\n\nconst serializePrerenderOutput = async (\n repoRoot: string,\n output: NextPrerenderOutput\n): Promise<GigadriveNextPrerenderOutput> => {\n const { bypassFor, ...prerenderConfig } = output.config;\n return {\n id: output.id,\n type: 'PRERENDER',\n pathname: output.pathname,\n parentOutputId: output.parentOutputId,\n groupId: output.groupId,\n ...(output.pprChain ? { pprChain: output.pprChain } : {}),\n ...(output.parentFallbackMode !== undefined ? { parentFallbackMode: toJsonValue(output.parentFallbackMode) } : {}),\n ...(output.fallback\n ? {\n fallback: {\n ...(output.fallback.filePath\n ? { filePath: await requireReadableFile(repoRoot, output.fallback.filePath) }\n : {}),\n ...(output.fallback.initialStatus !== undefined ? { initialStatus: output.fallback.initialStatus } : {}),\n ...(output.fallback.initialHeaders ? { initialHeaders: output.fallback.initialHeaders } : {}),\n ...(output.fallback.initialExpiration !== undefined\n ? { initialExpiration: output.fallback.initialExpiration }\n : {}),\n ...(output.fallback.initialRevalidate !== undefined\n ? { initialRevalidate: output.fallback.initialRevalidate }\n : {}),\n ...(output.fallback.postponedState !== undefined ? { postponedState: output.fallback.postponedState } : {}),\n },\n }\n : {}),\n config: {\n ...prerenderConfig,\n ...(bypassFor ? { bypassFor: toJsonValue(bypassFor) as JsonValue[] } : {}),\n },\n };\n};\n\n/**\n * Collapses per-route runtime config onto the one standalone server. `maxDuration`\n * becomes the max across routes (one function honors one limit); `env` is the union\n * of every route's declared env (the single server runs them all in-process).\n */\nconst aggregateServerDescriptor = (outputs: NextRouteOutput[]): GigadriveNextServerDescriptor => {\n let maxDuration: number | undefined;\n const env: Record<string, string> = {};\n for (const output of outputs) {\n if (output.config.maxDuration !== undefined) {\n maxDuration = Math.max(maxDuration ?? 0, output.config.maxDuration);\n }\n if (output.config.env) Object.assign(env, output.config.env);\n }\n return {\n ...(maxDuration !== undefined ? { maxDuration } : {}),\n ...(Object.keys(env).length > 0 ? { env } : {}),\n };\n};\n\ntype CollectBuildTracesModule = {\n collectBuildTraces: (options: {\n dir: string;\n config: BuildCompleteContext['config'];\n distDir: string;\n edgeRuntimeRoutes: Record<string, never>;\n staticPages: string[];\n outputFileTracingRoot: string;\n }) => Promise<void>;\n};\n\n/**\n * Next 16.3 stopped emitting the aggregated `next-server.js.nft.json` /\n * `next-minimal-server.js.nft.json` traces from Turbopack builds whenever an\n * adapter is configured, yet `next build` still runs the `output: 'standalone'`\n * writer after `onBuildComplete` — and that writer reads exactly this file, so\n * the build dies with ENOENT. Next 16.2 and all webpack builds still emit the\n * file, making this a no-op there. When the file is missing, regenerate both\n * aggregate traces with Next's own `collectBuildTraces` (the module the webpack\n * pipeline runs); without `buildTraceContext` it only writes the two aggregate\n * trace files and leaves Turbopack's per-entry traces untouched.\n */\nasync function ensureStandaloneServerTraces(\n projectDir: string,\n repoRoot: string,\n distDir: string,\n config: BuildCompleteContext['config']\n): Promise<void> {\n const aggregateTracePath = path.join(distDir, 'next-server.js.nft.json');\n try {\n await access(aggregateTracePath);\n return;\n } catch {\n // Missing — Next will crash in its standalone writer unless we regenerate it.\n }\n let collectBuildTracesModule: CollectBuildTracesModule;\n try {\n const projectRequire = createRequire(path.join(projectDir, 'package.json'));\n collectBuildTracesModule = projectRequire('next/dist/build/collect-build-traces') as CollectBuildTracesModule;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Next.js did not emit ${aggregateTracePath} and the Gigadrive adapter could not load ` +\n `next/dist/build/collect-build-traces from the project to regenerate it: ${message}`\n );\n }\n try {\n await collectBuildTracesModule.collectBuildTraces({\n dir: projectDir,\n config,\n distDir,\n edgeRuntimeRoutes: {},\n staticPages: [],\n outputFileTracingRoot: (config as { outputFileTracingRoot?: string }).outputFileTracingRoot ?? repoRoot,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Regenerating the Next.js standalone server traces (${aggregateTracePath}) failed: ${message}`);\n }\n}\n\nconst normalizeImages = (config: BuildCompleteContext['config']): NormalizedImagePolicy | undefined => {\n if (config.images.unoptimized) return undefined;\n return {\n localPatterns: config.images.localPatterns ?? [{ pathname: '/**' }],\n remotePatterns: config.images.remotePatterns.map((pattern) => {\n if (pattern instanceof URL) {\n return {\n protocol: pattern.protocol === 'http:' ? ('http' as const) : ('https' as const),\n hostname: pattern.hostname,\n port: pattern.port,\n pathname: pattern.pathname,\n search: pattern.search,\n };\n }\n return { ...pattern };\n }),\n widths: [...new Set([...config.images.deviceSizes, ...config.images.imageSizes])].sort((a, b) => a - b),\n heights: [],\n qualities: config.images.qualities ?? [75],\n formats: config.images.formats,\n minimumCacheTTL: config.images.minimumCacheTTL,\n dangerouslyAllowSVG: config.images.dangerouslyAllowSVG,\n contentSecurityPolicy: config.images.contentSecurityPolicy,\n contentDispositionType: config.images.contentDispositionType,\n maximumRedirects: config.images.maximumRedirects,\n maximumResponseBody: config.images.maximumResponseBody,\n variants: {},\n };\n};\n\n/**\n * Next.js deployment adapter used automatically by Gigadrive Network build workers.\n *\n * Next 16.2 and newer run the entire deployment as a single `output: 'standalone'`\n * server (one function per deployment) while the injected cache handlers, image\n * loader, and this hook's `onBuildComplete` metadata keep ISR, PPR, `use cache`,\n * and image optimization working through the platform's durable runtime-cache and\n * edge image services. Older releases retain the legacy standalone behavior without\n * the managed-runtime injections.\n */\nconst gigadriveNextAdapter: NextAdapter = {\n name: 'Gigadrive Network',\n\n modifyConfig(config, { phase, nextVersion }) {\n if (phase !== PRODUCTION_BUILD_PHASE) return config;\n\n const deploymentId = config.deploymentId ?? process.env.GIGADRIVE_DEPLOYMENT_ID;\n if (!supportsManagedRuntime(nextVersion)) {\n return {\n ...config,\n ...(deploymentId ? { deploymentId } : {}),\n output: config.output === 'export' ? 'export' : 'standalone',\n };\n }\n if (config.output === 'export') {\n return { ...config, ...(deploymentId ? { deploymentId } : {}) };\n }\n\n const injectCacheHandler = config.cacheHandler === undefined;\n const injectCacheComponentHandlers = config.cacheHandlers === undefined;\n const images = config.images;\n const injectImageLoader =\n images !== undefined && images.unoptimized !== true && images.loader === 'default' && !images.loaderFile;\n\n return {\n ...config,\n ...(deploymentId ? { deploymentId } : {}),\n // Run the whole deployment as one standalone Next server rather than a\n // serverless function per route. `onBuildComplete` still fires under\n // standalone (Next >= 16.2), and the standalone server natively honors the\n // injected cache handlers and resumes PPR from its incremental cache, so\n // ISR/PPR/`use cache` stay durable via the remote runtime-cache service.\n // Validated on Next 16.2.x (see MANAGED_STANDALONE_VALIDATED_MAX_MAJOR);\n // a future major that forbids adapter + standalone fails loudly at build.\n output: 'standalone',\n ...(injectCacheHandler ? { cacheHandler: CACHE_HANDLER_PATH() } : {}),\n ...(injectCacheComponentHandlers\n ? {\n cacheHandlers: {\n default: CACHE_COMPONENTS_HANDLER_PATH(),\n remote: CACHE_COMPONENTS_HANDLER_PATH(),\n },\n }\n : {}),\n ...(injectCacheHandler || injectCacheComponentHandlers ? { cacheMaxMemorySize: 0 } : {}),\n ...(injectImageLoader\n ? {\n images: {\n ...images,\n loader: 'custom',\n loaderFile: IMAGE_LOADER_PATH(),\n },\n }\n : {}),\n };\n },\n\n async onBuildComplete({ projectDir, repoRoot, distDir, config, nextVersion, buildId, routing, outputs }) {\n const metadataDirectory = path.join(projectDir, '.gigadrive');\n await mkdir(metadataDirectory, { recursive: true });\n const manifestPath = path.join(metadataDirectory, 'nextjs.json');\n const writeManifest = (manifest: unknown) =>\n writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8');\n\n if (!supportsManagedRuntime(nextVersion)) {\n const manifest: GigadriveNextBuildManifestV1 = {\n version: 1,\n output: config.output === 'export' ? 'export' : 'standalone',\n distDir: toPortableRelativePath(projectDir, distDir),\n repoRootToProject: toPortableRelativePath(repoRoot, projectDir, true),\n nextVersion,\n buildId,\n };\n await writeManifest(manifest);\n return;\n }\n\n const portableDistDir = toPortableRelativePath(projectDir, distDir);\n const repoRootToProject = toPortableRelativePath(repoRoot, projectDir, true);\n\n if (config.output === 'export') {\n const manifest: GigadriveNextBuildManifestV2Export = {\n version: 2,\n mode: 'export',\n distDir: portableDistDir,\n repoRootToProject,\n nextVersion,\n buildId,\n };\n await writeManifest(manifest);\n return;\n }\n\n if (config.output === 'standalone') {\n await ensureStandaloneServerTraces(projectDir, repoRoot, distDir, config);\n }\n\n const prerenders = await Promise.all(\n outputs.prerenders.map((output) => serializePrerenderOutput(repoRoot, output))\n );\n const server = aggregateServerDescriptor([\n ...outputs.pages,\n ...outputs.pagesApi,\n ...outputs.appPages,\n ...outputs.appRoutes,\n ...(outputs.middleware ? [outputs.middleware] : []),\n ]);\n const images = normalizeImages(config);\n // `.next/static` is thousands of content-hashed, immutable chunks. Register\n // the whole subtree as one edge-served prefix instead of enumerating files.\n const staticAssets: GigadriveNextStaticAssetPrefix[] = [\n { sourceDir: `${portableDistDir}/static`, urlPrefix: '_next/static', immutable: true },\n ];\n\n const manifest: GigadriveNextBuildManifestV2Standalone = {\n version: 2,\n mode: 'standalone-v2',\n distDir: portableDistDir,\n repoRootToProject,\n nextVersion,\n buildId,\n server,\n config: {\n basePath: config.basePath,\n trailingSlash: config.trailingSlash,\n cacheComponents: config.cacheComponents,\n ...(config.i18n ? { i18n: toJsonValue(config.i18n) } : {}),\n ...(images ? { images } : {}),\n },\n routing: {\n beforeMiddleware: toJsonValue(routing.beforeMiddleware) as JsonValue[],\n beforeFiles: toJsonValue(routing.beforeFiles) as JsonValue[],\n afterFiles: toJsonValue(routing.afterFiles) as JsonValue[],\n dynamicRoutes: toJsonValue(routing.dynamicRoutes) as JsonValue[],\n onMatch: toJsonValue(routing.onMatch) as JsonValue[],\n fallback: toJsonValue(routing.fallback) as JsonValue[],\n shouldNormalizeNextData: routing.shouldNormalizeNextData,\n rsc: toJsonValue(routing.rsc),\n },\n outputs: { prerenders, staticAssets },\n };\n await writeManifest(manifest);\n },\n};\n\nexport { MANAGED_STANDALONE_VALIDATED_MAX_MAJOR };\nexport default gigadriveNextAdapter;\n"],"mappings":"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","names":["manifest"]}
|
|
@@ -155,6 +155,7 @@ var getRuntimeCacheTagState = async (kind, tags) => {
|
|
|
155
155
|
}
|
|
156
156
|
};
|
|
157
157
|
var registerResumeRewarm = () => {
|
|
158
|
+
if (Reflect.has(globalThis, "EdgeRuntime")) return;
|
|
158
159
|
if (process.env.GIGADRIVE_NEXT_BUILD === "1") return;
|
|
159
160
|
const onGigadrive = process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;
|
|
160
161
|
if (!onGigadrive) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nextjs-cache-components-handler.ts","../src/nextjs-runtime-cache-client.ts"],"sourcesContent":["import {\n getRuntimeCacheTagState,\n readRuntimeCache,\n revalidateRuntimeCacheTags,\n writeRuntimeCache,\n} from './nextjs-runtime-cache-client';\n\ninterface CacheComponentEntry {\n value: ReadableStream<Uint8Array>;\n tags: string[];\n stale: number;\n timestamp: number;\n expire: number;\n revalidate: number;\n}\n\ninterface SerializedCacheComponentEntry extends Omit<CacheComponentEntry, 'value'> {\n value: Uint8Array;\n}\n\nconst isSerializedCacheComponentEntry = (value: unknown): value is SerializedCacheComponentEntry => {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Partial<SerializedCacheComponentEntry>;\n return (\n entry.value instanceof Uint8Array &&\n Array.isArray(entry.tags) &&\n entry.tags.every((tag) => typeof tag === 'string') &&\n typeof entry.stale === 'number' &&\n typeof entry.timestamp === 'number' &&\n typeof entry.expire === 'number' &&\n typeof entry.revalidate === 'number'\n );\n};\n\nconst pendingWrites = new Map<string, Promise<void>>();\nconst buildEntries = new Map<string, SerializedCacheComponentEntry>();\n\nconst streamToBytes = async (stream: ReadableStream<Uint8Array>): Promise<Uint8Array> => {\n const chunks: Uint8Array[] = [];\n let size = 0;\n const reader = stream.getReader();\n while (true) {\n const result = await reader.read();\n if (result.done) break;\n chunks.push(result.value);\n size += result.value.byteLength;\n }\n const bytes = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return bytes;\n};\n\n/** Shared Network cache handler for Next.js Cache Components and `use cache`. */\nconst cacheHandler = {\n async get(cacheKey: string, softTags: string[]): Promise<CacheComponentEntry | undefined> {\n await pendingWrites.get(cacheKey);\n const value =\n process.env.GIGADRIVE_NEXT_BUILD === '1'\n ? buildEntries.get(cacheKey)\n : await readRuntimeCache('component', cacheKey);\n if (!isSerializedCacheComponentEntry(value)) return undefined;\n const tagState =\n process.env.GIGADRIVE_NEXT_BUILD === '1'\n ? { stale: 0, expired: 0 }\n : await getRuntimeCacheTagState('component', [...new Set([...value.tags, ...softTags])]);\n if (tagState.expired > value.timestamp) return undefined;\n return {\n ...value,\n ...(tagState.stale > value.timestamp ? { revalidate: -1 } : {}),\n value: new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(value.value);\n controller.close();\n },\n }),\n };\n },\n\n async set(cacheKey: string, pendingEntry: Promise<CacheComponentEntry>): Promise<void> {\n const write = (async () => {\n const entry = await pendingEntry;\n const value = await streamToBytes(entry.value);\n const serializedEntry = { ...entry, value };\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') {\n buildEntries.set(cacheKey, serializedEntry);\n } else {\n await writeRuntimeCache('component', cacheKey, serializedEntry, entry.tags);\n }\n })();\n pendingWrites.set(cacheKey, write);\n try {\n await write;\n } finally {\n if (pendingWrites.get(cacheKey) === write) pendingWrites.delete(cacheKey);\n }\n },\n\n async refreshTags(): Promise<void> {},\n\n getExpiration(): Promise<number> {\n return Promise.resolve(Infinity);\n },\n\n async updateTags(tags: string[], durations?: { expire?: number }): Promise<void> {\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') {\n for (const [key, entry] of buildEntries) {\n if (entry.tags.some((tag) => tags.includes(tag))) buildEntries.delete(key);\n }\n return;\n }\n return revalidateRuntimeCacheTags('component', tags, durations);\n },\n};\n\nexport default cacheHandler;\n","interface RuntimeCacheEnvelope {\n value: unknown;\n}\n\ninterface AccessTokenResponse {\n access_token: string;\n expires_in?: number;\n}\n\nexport interface RuntimeCacheTagState {\n stale: number;\n expired: number;\n}\n\nlet cachedToken: { value: string; expiresAt: number } | undefined;\n\nconst apiBaseUrl = (): string => (process.env.GIGADRIVE_API_URL ?? 'https://api.gigadrive.network').replace(/\\/$/, '');\n\nconst encodeBinary = (value: unknown, seen = new WeakSet<object>()): unknown => {\n if (value instanceof Uint8Array) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n if (value instanceof ArrayBuffer) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n // Next stores App Router RSC segment payloads as a `Map<string, Buffer>`\n // (`segmentData`). `Object.entries` on a Map yields nothing, so without an\n // explicit branch the whole map would serialize to `{}` and every prefetched\n // segment would be silently lost on the next read.\n if (value instanceof Map) {\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const entries = [...value.entries()].map(([key, item]) => [encodeBinary(key, seen), encodeBinary(item, seen)]);\n seen.delete(value);\n return { __gigadriveType: 'map', value: entries };\n }\n if (Array.isArray(value)) return value.map((item) => encodeBinary(item, seen));\n if (typeof value !== 'object' || value === null) return value;\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) result[key] = encodeBinary(item, seen);\n seen.delete(value);\n return result;\n};\n\nconst decodeBinary = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(decodeBinary);\n if (typeof value !== 'object' || value === null) return value;\n const record = value as Record<string, unknown>;\n if (record.__gigadriveType === 'bytes' && typeof record.value === 'string')\n return Buffer.from(record.value, 'base64');\n if (record.__gigadriveType === 'map' && Array.isArray(record.value)) {\n return new Map(\n (record.value as unknown[]).map((entry) => {\n const [key, item] = entry as [unknown, unknown];\n return [decodeBinary(key), decodeBinary(item)];\n })\n );\n }\n return Object.fromEntries(Object.entries(record).map(([key, item]) => [key, decodeBinary(item)]));\n};\n\nconst getAccessToken = async (): Promise<string> => {\n if (cachedToken && cachedToken.expiresAt > Date.now() + 30_000) return cachedToken.value;\n const clientId = process.env.GIGADRIVE_CLIENT_ID;\n const clientSecret = process.env.GIGADRIVE_CLIENT_SECRET;\n if (!clientId || !clientSecret) throw new Error('Gigadrive workload credentials are unavailable');\n\n const response = await fetch(`${apiBaseUrl()}/oauth2/token`, {\n method: 'POST',\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,\n 'content-type': 'application/x-www-form-urlencoded',\n },\n body: 'grant_type=client_credentials',\n });\n if (!response.ok) throw new Error(`Gigadrive workload authentication failed with status ${response.status}`);\n const token = (await response.json()) as AccessTokenResponse;\n if (!token.access_token) throw new Error('Gigadrive workload authentication returned no access token');\n cachedToken = {\n value: token.access_token,\n expiresAt: Date.now() + Math.max(60, token.expires_in ?? 300) * 1000,\n };\n return token.access_token;\n};\n\nconst request = async (pathname: string, init: RequestInit, attempt = 0): Promise<Response> => {\n const token = await getAccessToken();\n try {\n const response = await fetch(`${apiBaseUrl()}${pathname}`, {\n ...init,\n headers: {\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n 'x-gigadrive-deployment-id': process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? '',\n 'x-gigadrive-build-id': process.env.NEXT_BUILD_ID ?? '',\n ...init.headers,\n },\n });\n if (response.status === 401 && attempt === 0) {\n cachedToken = undefined;\n return request(pathname, init, attempt + 1);\n }\n if (response.status >= 500 && attempt < 2) return request(pathname, init, attempt + 1);\n return response;\n } catch (error) {\n if (attempt < 2) return request(pathname, init, attempt + 1);\n throw error;\n }\n};\n\nconst cachePath = (kind: string, key: string): string =>\n `/internal/runtime-cache/v1/entries/${encodeURIComponent(kind)}/${encodeURIComponent(key)}`;\n\nexport const readRuntimeCache = async (kind: string, key: string): Promise<unknown | undefined> => {\n try {\n const response = await request(cachePath(kind, key), { method: 'GET' });\n if (response.status === 404) return undefined;\n if (!response.ok) return undefined;\n const envelope = (await response.json()) as RuntimeCacheEnvelope;\n return decodeBinary(envelope.value);\n } catch {\n return undefined;\n }\n};\n\nexport const writeRuntimeCache = async (\n kind: string,\n key: string,\n value: unknown,\n tags: readonly string[] = []\n): Promise<void> => {\n const response = await request(cachePath(kind, key), {\n method: 'PUT',\n body: JSON.stringify({ value: encodeBinary(value), tags }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache write failed with status ${response.status}`);\n};\n\nexport const revalidateRuntimeCacheTags = async (\n kind: string,\n tags: readonly string[],\n durations?: { expire?: number }\n): Promise<void> => {\n const response = await request('/internal/runtime-cache/v1/tags/revalidate', {\n method: 'POST',\n body: JSON.stringify({ kind, tags, durations }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache revalidation failed with status ${response.status}`);\n};\n\nexport const getRuntimeCacheTagExpiration = async (kind: string, tags: readonly string[]): Promise<number> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/expiration', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return 0;\n const value = (await response.json()) as { expiration?: unknown };\n return typeof value.expiration === 'number' ? value.expiration : 0;\n } catch {\n return 0;\n }\n};\n\nexport const getRuntimeCacheTagState = async (kind: string, tags: readonly string[]): Promise<RuntimeCacheTagState> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/state', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return { stale: 0, expired: 0 };\n const value = (await response.json()) as { stale?: unknown; expired?: unknown };\n return {\n stale: typeof value.stale === 'number' ? value.stale : 0,\n expired: typeof value.expired === 'number' ? value.expired : 0,\n };\n } catch {\n return { stale: 0, expired: 0 };\n }\n};\n\nexport const resetRuntimeCacheClientForTests = (): void => {\n cachedToken = undefined;\n};\n\n/**\n * Re-establishes the client's network state after a microVM resume.\n *\n * The guest runtime delivers SIGUSR2 when the instance is restored from a\n * suspend snapshot. At that moment every kept-alive TCP connection from before\n * the freeze is dead, and the cached OAuth token may have expired while the\n * clock was stopped. Dropping the token and dialing one throwaway read\n * re-opens TCP+TLS and refreshes the token concurrently with the guest's own\n * wake-up work, so the first real cache read after a resume does not\n * serialize behind reconnection.\n *\n * Registered only when a Gigadrive deployment marker is present in the\n * environment, so local `next dev`/`next build` never gains a signal listener.\n */\nconst registerResumeRewarm = (): void => {\n // The deployment id is intentionally available during `next build`, but the\n // shared cache client is also bundled into Edge routes at that point. Keep\n // every Node-only signal reference behind the build-phase guard so Turbopack\n // can eliminate this branch before its Edge runtime validation runs.\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') return;\n\n const onGigadrive =\n process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;\n if (!onGigadrive) return;\n\n // This module is shared by Node and Edge cache-handler bundles. Next.js 16.2\n // rejects a statically analyzable `process.on` call while collecting Edge\n // route data, even though the listener only runs inside the Node runtime.\n // Resolve the optional Node signal API reflectively so Edge builds can load\n // the shared client while Node deployments retain resume rewarming.\n const runtimeProcess = Reflect.get(globalThis, 'process') as NodeJS.Process | undefined;\n const addSignalListener = runtimeProcess && Reflect.get(runtimeProcess, 'on');\n if (typeof addSignalListener !== 'function') return;\n\n Reflect.apply(addSignalListener, runtimeProcess, [\n 'SIGUSR2',\n () => {\n cachedToken = undefined;\n if (!process.env.GIGADRIVE_CLIENT_ID || !process.env.GIGADRIVE_CLIENT_SECRET) return;\n void readRuntimeCache('warmup', '__resume__');\n },\n ]);\n};\nregisterResumeRewarm();\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/nextjs-cache-components-handler.ts","../src/nextjs-runtime-cache-client.ts"],"sourcesContent":["import {\n getRuntimeCacheTagState,\n readRuntimeCache,\n revalidateRuntimeCacheTags,\n writeRuntimeCache,\n} from './nextjs-runtime-cache-client';\n\ninterface CacheComponentEntry {\n value: ReadableStream<Uint8Array>;\n tags: string[];\n stale: number;\n timestamp: number;\n expire: number;\n revalidate: number;\n}\n\ninterface SerializedCacheComponentEntry extends Omit<CacheComponentEntry, 'value'> {\n value: Uint8Array;\n}\n\nconst isSerializedCacheComponentEntry = (value: unknown): value is SerializedCacheComponentEntry => {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Partial<SerializedCacheComponentEntry>;\n return (\n entry.value instanceof Uint8Array &&\n Array.isArray(entry.tags) &&\n entry.tags.every((tag) => typeof tag === 'string') &&\n typeof entry.stale === 'number' &&\n typeof entry.timestamp === 'number' &&\n typeof entry.expire === 'number' &&\n typeof entry.revalidate === 'number'\n );\n};\n\nconst pendingWrites = new Map<string, Promise<void>>();\nconst buildEntries = new Map<string, SerializedCacheComponentEntry>();\n\nconst streamToBytes = async (stream: ReadableStream<Uint8Array>): Promise<Uint8Array> => {\n const chunks: Uint8Array[] = [];\n let size = 0;\n const reader = stream.getReader();\n while (true) {\n const result = await reader.read();\n if (result.done) break;\n chunks.push(result.value);\n size += result.value.byteLength;\n }\n const bytes = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return bytes;\n};\n\n/** Shared Network cache handler for Next.js Cache Components and `use cache`. */\nconst cacheHandler = {\n async get(cacheKey: string, softTags: string[]): Promise<CacheComponentEntry | undefined> {\n await pendingWrites.get(cacheKey);\n const value =\n process.env.GIGADRIVE_NEXT_BUILD === '1'\n ? buildEntries.get(cacheKey)\n : await readRuntimeCache('component', cacheKey);\n if (!isSerializedCacheComponentEntry(value)) return undefined;\n const tagState =\n process.env.GIGADRIVE_NEXT_BUILD === '1'\n ? { stale: 0, expired: 0 }\n : await getRuntimeCacheTagState('component', [...new Set([...value.tags, ...softTags])]);\n if (tagState.expired > value.timestamp) return undefined;\n return {\n ...value,\n ...(tagState.stale > value.timestamp ? { revalidate: -1 } : {}),\n value: new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(value.value);\n controller.close();\n },\n }),\n };\n },\n\n async set(cacheKey: string, pendingEntry: Promise<CacheComponentEntry>): Promise<void> {\n const write = (async () => {\n const entry = await pendingEntry;\n const value = await streamToBytes(entry.value);\n const serializedEntry = { ...entry, value };\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') {\n buildEntries.set(cacheKey, serializedEntry);\n } else {\n await writeRuntimeCache('component', cacheKey, serializedEntry, entry.tags);\n }\n })();\n pendingWrites.set(cacheKey, write);\n try {\n await write;\n } finally {\n if (pendingWrites.get(cacheKey) === write) pendingWrites.delete(cacheKey);\n }\n },\n\n async refreshTags(): Promise<void> {},\n\n getExpiration(): Promise<number> {\n return Promise.resolve(Infinity);\n },\n\n async updateTags(tags: string[], durations?: { expire?: number }): Promise<void> {\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') {\n for (const [key, entry] of buildEntries) {\n if (entry.tags.some((tag) => tags.includes(tag))) buildEntries.delete(key);\n }\n return;\n }\n return revalidateRuntimeCacheTags('component', tags, durations);\n },\n};\n\nexport default cacheHandler;\n","interface RuntimeCacheEnvelope {\n value: unknown;\n}\n\ninterface AccessTokenResponse {\n access_token: string;\n expires_in?: number;\n}\n\nexport interface RuntimeCacheTagState {\n stale: number;\n expired: number;\n}\n\nlet cachedToken: { value: string; expiresAt: number } | undefined;\n\nconst apiBaseUrl = (): string => (process.env.GIGADRIVE_API_URL ?? 'https://api.gigadrive.network').replace(/\\/$/, '');\n\nconst encodeBinary = (value: unknown, seen = new WeakSet<object>()): unknown => {\n if (value instanceof Uint8Array) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n if (value instanceof ArrayBuffer) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n // Next stores App Router RSC segment payloads as a `Map<string, Buffer>`\n // (`segmentData`). `Object.entries` on a Map yields nothing, so without an\n // explicit branch the whole map would serialize to `{}` and every prefetched\n // segment would be silently lost on the next read.\n if (value instanceof Map) {\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const entries = [...value.entries()].map(([key, item]) => [encodeBinary(key, seen), encodeBinary(item, seen)]);\n seen.delete(value);\n return { __gigadriveType: 'map', value: entries };\n }\n if (Array.isArray(value)) return value.map((item) => encodeBinary(item, seen));\n if (typeof value !== 'object' || value === null) return value;\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) result[key] = encodeBinary(item, seen);\n seen.delete(value);\n return result;\n};\n\nconst decodeBinary = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(decodeBinary);\n if (typeof value !== 'object' || value === null) return value;\n const record = value as Record<string, unknown>;\n if (record.__gigadriveType === 'bytes' && typeof record.value === 'string')\n return Buffer.from(record.value, 'base64');\n if (record.__gigadriveType === 'map' && Array.isArray(record.value)) {\n return new Map(\n (record.value as unknown[]).map((entry) => {\n const [key, item] = entry as [unknown, unknown];\n return [decodeBinary(key), decodeBinary(item)];\n })\n );\n }\n return Object.fromEntries(Object.entries(record).map(([key, item]) => [key, decodeBinary(item)]));\n};\n\nconst getAccessToken = async (): Promise<string> => {\n if (cachedToken && cachedToken.expiresAt > Date.now() + 30_000) return cachedToken.value;\n const clientId = process.env.GIGADRIVE_CLIENT_ID;\n const clientSecret = process.env.GIGADRIVE_CLIENT_SECRET;\n if (!clientId || !clientSecret) throw new Error('Gigadrive workload credentials are unavailable');\n\n const response = await fetch(`${apiBaseUrl()}/oauth2/token`, {\n method: 'POST',\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,\n 'content-type': 'application/x-www-form-urlencoded',\n },\n body: 'grant_type=client_credentials',\n });\n if (!response.ok) throw new Error(`Gigadrive workload authentication failed with status ${response.status}`);\n const token = (await response.json()) as AccessTokenResponse;\n if (!token.access_token) throw new Error('Gigadrive workload authentication returned no access token');\n cachedToken = {\n value: token.access_token,\n expiresAt: Date.now() + Math.max(60, token.expires_in ?? 300) * 1000,\n };\n return token.access_token;\n};\n\nconst request = async (pathname: string, init: RequestInit, attempt = 0): Promise<Response> => {\n const token = await getAccessToken();\n try {\n const response = await fetch(`${apiBaseUrl()}${pathname}`, {\n ...init,\n headers: {\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n 'x-gigadrive-deployment-id': process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? '',\n 'x-gigadrive-build-id': process.env.NEXT_BUILD_ID ?? '',\n ...init.headers,\n },\n });\n if (response.status === 401 && attempt === 0) {\n cachedToken = undefined;\n return request(pathname, init, attempt + 1);\n }\n if (response.status >= 500 && attempt < 2) return request(pathname, init, attempt + 1);\n return response;\n } catch (error) {\n if (attempt < 2) return request(pathname, init, attempt + 1);\n throw error;\n }\n};\n\nconst cachePath = (kind: string, key: string): string =>\n `/internal/runtime-cache/v1/entries/${encodeURIComponent(kind)}/${encodeURIComponent(key)}`;\n\nexport const readRuntimeCache = async (kind: string, key: string): Promise<unknown | undefined> => {\n try {\n const response = await request(cachePath(kind, key), { method: 'GET' });\n if (response.status === 404) return undefined;\n if (!response.ok) return undefined;\n const envelope = (await response.json()) as RuntimeCacheEnvelope;\n return decodeBinary(envelope.value);\n } catch {\n return undefined;\n }\n};\n\nexport const writeRuntimeCache = async (\n kind: string,\n key: string,\n value: unknown,\n tags: readonly string[] = []\n): Promise<void> => {\n const response = await request(cachePath(kind, key), {\n method: 'PUT',\n body: JSON.stringify({ value: encodeBinary(value), tags }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache write failed with status ${response.status}`);\n};\n\nexport const revalidateRuntimeCacheTags = async (\n kind: string,\n tags: readonly string[],\n durations?: { expire?: number }\n): Promise<void> => {\n const response = await request('/internal/runtime-cache/v1/tags/revalidate', {\n method: 'POST',\n body: JSON.stringify({ kind, tags, durations }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache revalidation failed with status ${response.status}`);\n};\n\nexport const getRuntimeCacheTagExpiration = async (kind: string, tags: readonly string[]): Promise<number> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/expiration', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return 0;\n const value = (await response.json()) as { expiration?: unknown };\n return typeof value.expiration === 'number' ? value.expiration : 0;\n } catch {\n return 0;\n }\n};\n\nexport const getRuntimeCacheTagState = async (kind: string, tags: readonly string[]): Promise<RuntimeCacheTagState> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/state', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return { stale: 0, expired: 0 };\n const value = (await response.json()) as { stale?: unknown; expired?: unknown };\n return {\n stale: typeof value.stale === 'number' ? value.stale : 0,\n expired: typeof value.expired === 'number' ? value.expired : 0,\n };\n } catch {\n return { stale: 0, expired: 0 };\n }\n};\n\nexport const resetRuntimeCacheClientForTests = (): void => {\n cachedToken = undefined;\n};\n\n/**\n * Re-establishes the client's network state after a microVM resume.\n *\n * The guest runtime delivers SIGUSR2 when the instance is restored from a\n * suspend snapshot. At that moment every kept-alive TCP connection from before\n * the freeze is dead, and the cached OAuth token may have expired while the\n * clock was stopped. Dropping the token and dialing one throwaway read\n * re-opens TCP+TLS and refreshes the token concurrently with the guest's own\n * wake-up work, so the first real cache read after a resume does not\n * serialize behind reconnection.\n *\n * Registered only when a Gigadrive deployment marker is present in the\n * environment, so local `next dev`/`next build` never gains a signal listener.\n */\nconst registerResumeRewarm = (): void => {\n // Next exposes this marker before evaluating an Edge route bundle. Bail out\n // before touching `process`: its Edge compatibility proxy throws when the\n // Node-only signal API is read, including through Reflect.\n if (Reflect.has(globalThis, 'EdgeRuntime')) return;\n\n // The deployment id is intentionally available during `next build`, but the\n // shared cache client is also bundled into Edge routes at that point. Keep\n // every Node-only signal reference behind the build-phase guard so Turbopack\n // can eliminate this branch before its Edge runtime validation runs.\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') return;\n\n const onGigadrive =\n process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;\n if (!onGigadrive) return;\n\n // Resolve the optional Node signal API reflectively so non-Node runtimes can\n // load the shared client while Node deployments retain resume rewarming.\n const runtimeProcess = Reflect.get(globalThis, 'process') as NodeJS.Process | undefined;\n const addSignalListener = runtimeProcess && Reflect.get(runtimeProcess, 'on');\n if (typeof addSignalListener !== 'function') return;\n\n Reflect.apply(addSignalListener, runtimeProcess, [\n 'SIGUSR2',\n () => {\n cachedToken = undefined;\n if (!process.env.GIGADRIVE_CLIENT_ID || !process.env.GIGADRIVE_CLIENT_SECRET) return;\n void readRuntimeCache('warmup', '__resume__');\n },\n ]);\n};\nregisterResumeRewarm();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACcA,IAAI;AAEJ,IAAM,aAAa,OAAe,QAAQ,IAAI,qBAAqB,iCAAiC,QAAQ,OAAO,EAAE;AAErH,IAAM,eAAe,CAAC,OAAgB,OAAO,oBAAI,QAAgB,MAAe;AAC9E,MAAI,iBAAiB,YAAY;AAC/B,WAAO,EAAE,iBAAiB,SAAS,OAAO,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ,EAAE;AAAA,EAClF;AACA,MAAI,iBAAiB,aAAa;AAChC,WAAO,EAAE,iBAAiB,SAAS,OAAO,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ,EAAE;AAAA,EAClF;AAKA,MAAI,iBAAiB,KAAK;AACxB,QAAI,KAAK,IAAI,KAAK,EAAG,OAAM,IAAI,MAAM,+CAA+C;AACpF,SAAK,IAAI,KAAK;AACd,UAAM,UAAU,CAAC,GAAG,MAAM,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,aAAa,KAAK,IAAI,GAAG,aAAa,MAAM,IAAI,CAAC,CAAC;AAC7G,SAAK,OAAO,KAAK;AACjB,WAAO,EAAE,iBAAiB,OAAO,OAAO,QAAQ;AAAA,EAClD;AACA,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,CAAC,SAAS,aAAa,MAAM,IAAI,CAAC;AAC7E,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,MAAI,KAAK,IAAI,KAAK,EAAG,OAAM,IAAI,MAAM,+CAA+C;AACpF,OAAK,IAAI,KAAK;AACd,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,EAAG,QAAO,GAAG,IAAI,aAAa,MAAM,IAAI;AACtF,OAAK,OAAO,KAAK;AACjB,SAAO;AACT;AAEA,IAAM,eAAe,CAAC,UAA4B;AAChD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,YAAY;AACvD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,SAAS;AACf,MAAI,OAAO,oBAAoB,WAAW,OAAO,OAAO,UAAU;AAChE,WAAO,OAAO,KAAK,OAAO,OAAO,QAAQ;AAC3C,MAAI,OAAO,oBAAoB,SAAS,MAAM,QAAQ,OAAO,KAAK,GAAG;AACnE,WAAO,IAAI;AAAA,MACR,OAAO,MAAoB,IAAI,CAAC,UAAU;AACzC,cAAM,CAAC,KAAK,IAAI,IAAI;AACpB,eAAO,CAAC,aAAa,GAAG,GAAG,aAAa,IAAI,CAAC;AAAA,MAC/C,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,aAAa,IAAI,CAAC,CAAC,CAAC;AAClG;AAEA,IAAM,iBAAiB,YAA6B;AAClD,MAAI,eAAe,YAAY,YAAY,KAAK,IAAI,IAAI,IAAQ,QAAO,YAAY;AACnF,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,eAAe,QAAQ,IAAI;AACjC,MAAI,CAAC,YAAY,CAAC,aAAc,OAAM,IAAI,MAAM,gDAAgD;AAEhG,QAAM,WAAW,MAAM,MAAM,GAAG,WAAW,CAAC,iBAAiB;AAAA,IAC3D,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,eAAe,SAAS,OAAO,KAAK,GAAG,QAAQ,IAAI,YAAY,EAAE,EAAE,SAAS,QAAQ,CAAC;AAAA,MACrF,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AACD,MAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,wDAAwD,SAAS,MAAM,EAAE;AAC3G,QAAM,QAAS,MAAM,SAAS,KAAK;AACnC,MAAI,CAAC,MAAM,aAAc,OAAM,IAAI,MAAM,4DAA4D;AACrG,gBAAc;AAAA,IACZ,OAAO,MAAM;AAAA,IACb,WAAW,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,cAAc,GAAG,IAAI;AAAA,EAClE;AACA,SAAO,MAAM;AACf;AAEA,IAAM,UAAU,OAAO,UAAkB,MAAmB,UAAU,MAAyB;AAC7F,QAAM,QAAQ,MAAM,eAAe;AACnC,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,QAAQ,IAAI;AAAA,MACzD,GAAG;AAAA,MACH,SAAS;AAAA,QACP,eAAe,UAAU,KAAK;AAAA,QAC9B,gBAAgB;AAAA,QAChB,6BAA6B,QAAQ,IAAI,2BAA2B,QAAQ,IAAI,wBAAwB;AAAA,QACxG,wBAAwB,QAAQ,IAAI,iBAAiB;AAAA,QACrD,GAAG,KAAK;AAAA,MACV;AAAA,IACF,CAAC;AACD,QAAI,SAAS,WAAW,OAAO,YAAY,GAAG;AAC5C,oBAAc;AACd,aAAO,QAAQ,UAAU,MAAM,UAAU,CAAC;AAAA,IAC5C;AACA,QAAI,SAAS,UAAU,OAAO,UAAU,EAAG,QAAO,QAAQ,UAAU,MAAM,UAAU,CAAC;AACrF,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,UAAU,EAAG,QAAO,QAAQ,UAAU,MAAM,UAAU,CAAC;AAC3D,UAAM;AAAA,EACR;AACF;AAEA,IAAM,YAAY,CAAC,MAAc,QAC/B,sCAAsC,mBAAmB,IAAI,CAAC,IAAI,mBAAmB,GAAG,CAAC;AAEpF,IAAM,mBAAmB,OAAO,MAAc,QAA8C;AACjG,MAAI;AACF,UAAM,WAAW,MAAM,QAAQ,UAAU,MAAM,GAAG,GAAG,EAAE,QAAQ,MAAM,CAAC;AACtE,QAAI,SAAS,WAAW,IAAK,QAAO;AACpC,QAAI,CAAC,SAAS,GAAI,QAAO;AACzB,UAAM,WAAY,MAAM,SAAS,KAAK;AACtC,WAAO,aAAa,SAAS,KAAK;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,oBAAoB,OAC/B,MACA,KACA,OACA,OAA0B,CAAC,MACT;AAClB,QAAM,WAAW,MAAM,QAAQ,UAAU,MAAM,GAAG,GAAG;AAAA,IACnD,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,EAAE,OAAO,aAAa,KAAK,GAAG,KAAK,CAAC;AAAA,EAC3D,CAAC;AACD,MAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,oDAAoD,SAAS,MAAM,EAAE;AACzG;AAEO,IAAM,6BAA6B,OACxC,MACA,MACA,cACkB;AAClB,QAAM,WAAW,MAAM,QAAQ,8CAA8C;AAAA,IAC3E,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,EAAE,MAAM,MAAM,UAAU,CAAC;AAAA,EAChD,CAAC;AACD,MAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,2DAA2D,SAAS,MAAM,EAAE;AAChH;AAgBO,IAAM,0BAA0B,OAAO,MAAc,SAA2D;AACrH,MAAI;AACF,UAAM,WAAW,MAAM,QAAQ,yCAAyC;AAAA,MACtE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AAAA,IACrC,CAAC;AACD,QAAI,CAAC,SAAS,GAAI,QAAO,EAAE,OAAO,GAAG,SAAS,EAAE;AAChD,UAAM,QAAS,MAAM,SAAS,KAAK;AACnC,WAAO;AAAA,MACL,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAAA,MACvD,SAAS,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU;AAAA,IAC/D;AAAA,EACF,QAAQ;AACN,WAAO,EAAE,OAAO,GAAG,SAAS,EAAE;AAAA,EAChC;AACF;AAoBA,IAAM,uBAAuB,MAAY;AAIvC,MAAI,QAAQ,IAAI,YAAY,aAAa,EAAG;AAM5C,MAAI,QAAQ,IAAI,yBAAyB,IAAK;AAE9C,QAAM,cACJ,QAAQ,IAAI,2BAA2B,QAAQ,IAAI,wBAAwB,QAAQ,IAAI;AACzF,MAAI,CAAC,YAAa;AAIlB,QAAM,iBAAiB,QAAQ,IAAI,YAAY,SAAS;AACxD,QAAM,oBAAoB,kBAAkB,QAAQ,IAAI,gBAAgB,IAAI;AAC5E,MAAI,OAAO,sBAAsB,WAAY;AAE7C,UAAQ,MAAM,mBAAmB,gBAAgB;AAAA,IAC/C;AAAA,IACA,MAAM;AACJ,oBAAc;AACd,UAAI,CAAC,QAAQ,IAAI,uBAAuB,CAAC,QAAQ,IAAI,wBAAyB;AAC9E,WAAK,iBAAiB,UAAU,YAAY;AAAA,IAC9C;AAAA,EACF,CAAC;AACH;AACA,qBAAqB;;;ADpNrB,IAAM,kCAAkC,CAAC,UAA2D;AAClG,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,QAAQ;AACd,SACE,MAAM,iBAAiB,cACvB,MAAM,QAAQ,MAAM,IAAI,KACxB,MAAM,KAAK,MAAM,CAAC,QAAQ,OAAO,QAAQ,QAAQ,KACjD,OAAO,MAAM,UAAU,YACvB,OAAO,MAAM,cAAc,YAC3B,OAAO,MAAM,WAAW,YACxB,OAAO,MAAM,eAAe;AAEhC;AAEA,IAAM,gBAAgB,oBAAI,IAA2B;AACrD,IAAM,eAAe,oBAAI,IAA2C;AAEpE,IAAM,gBAAgB,OAAO,WAA4D;AACvF,QAAM,SAAuB,CAAC;AAC9B,MAAI,OAAO;AACX,QAAM,SAAS,OAAO,UAAU;AAChC,SAAO,MAAM;AACX,UAAM,SAAS,MAAM,OAAO,KAAK;AACjC,QAAI,OAAO,KAAM;AACjB,WAAO,KAAK,OAAO,KAAK;AACxB,YAAQ,OAAO,MAAM;AAAA,EACvB;AACA,QAAM,QAAQ,IAAI,WAAW,IAAI;AACjC,MAAI,SAAS;AACb,aAAW,SAAS,QAAQ;AAC1B,UAAM,IAAI,OAAO,MAAM;AACvB,cAAU,MAAM;AAAA,EAClB;AACA,SAAO;AACT;AAGA,IAAM,eAAe;AAAA,EACnB,MAAM,IAAI,UAAkB,UAA8D;AACxF,UAAM,cAAc,IAAI,QAAQ;AAChC,UAAM,QACJ,QAAQ,IAAI,yBAAyB,MACjC,aAAa,IAAI,QAAQ,IACzB,MAAM,iBAAiB,aAAa,QAAQ;AAClD,QAAI,CAAC,gCAAgC,KAAK,EAAG,QAAO;AACpD,UAAM,WACJ,QAAQ,IAAI,yBAAyB,MACjC,EAAE,OAAO,GAAG,SAAS,EAAE,IACvB,MAAM,wBAAwB,aAAa,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;AAC3F,QAAI,SAAS,UAAU,MAAM,UAAW,QAAO;AAC/C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAI,SAAS,QAAQ,MAAM,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;AAAA,MAC7D,OAAO,IAAI,eAA2B;AAAA,QACpC,MAAM,YAAY;AAChB,qBAAW,QAAQ,MAAM,KAAK;AAC9B,qBAAW,MAAM;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,UAAkB,cAA2D;AACrF,UAAM,SAAS,YAAY;AACzB,YAAM,QAAQ,MAAM;AACpB,YAAM,QAAQ,MAAM,cAAc,MAAM,KAAK;AAC7C,YAAM,kBAAkB,EAAE,GAAG,OAAO,MAAM;AAC1C,UAAI,QAAQ,IAAI,yBAAyB,KAAK;AAC5C,qBAAa,IAAI,UAAU,eAAe;AAAA,MAC5C,OAAO;AACL,cAAM,kBAAkB,aAAa,UAAU,iBAAiB,MAAM,IAAI;AAAA,MAC5E;AAAA,IACF,GAAG;AACH,kBAAc,IAAI,UAAU,KAAK;AACjC,QAAI;AACF,YAAM;AAAA,IACR,UAAE;AACA,UAAI,cAAc,IAAI,QAAQ,MAAM,MAAO,eAAc,OAAO,QAAQ;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,MAAM,cAA6B;AAAA,EAAC;AAAA,EAEpC,gBAAiC;AAC/B,WAAO,QAAQ,QAAQ,QAAQ;AAAA,EACjC;AAAA,EAEA,MAAM,WAAW,MAAgB,WAAgD;AAC/E,QAAI,QAAQ,IAAI,yBAAyB,KAAK;AAC5C,iBAAW,CAAC,KAAK,KAAK,KAAK,cAAc;AACvC,YAAI,MAAM,KAAK,KAAK,CAAC,QAAQ,KAAK,SAAS,GAAG,CAAC,EAAG,cAAa,OAAO,GAAG;AAAA,MAC3E;AACA;AAAA,IACF;AACA,WAAO,2BAA2B,aAAa,MAAM,SAAS;AAAA,EAChE;AACF;AAEA,IAAO,0CAAQ;","names":[]}
|
|
@@ -129,6 +129,7 @@ var getRuntimeCacheTagState = async (kind, tags) => {
|
|
|
129
129
|
}
|
|
130
130
|
};
|
|
131
131
|
var registerResumeRewarm = () => {
|
|
132
|
+
if (Reflect.has(globalThis, "EdgeRuntime")) return;
|
|
132
133
|
if (process.env.GIGADRIVE_NEXT_BUILD === "1") return;
|
|
133
134
|
const onGigadrive = process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;
|
|
134
135
|
if (!onGigadrive) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nextjs-runtime-cache-client.ts","../src/nextjs-cache-components-handler.ts"],"sourcesContent":["interface RuntimeCacheEnvelope {\n value: unknown;\n}\n\ninterface AccessTokenResponse {\n access_token: string;\n expires_in?: number;\n}\n\nexport interface RuntimeCacheTagState {\n stale: number;\n expired: number;\n}\n\nlet cachedToken: { value: string; expiresAt: number } | undefined;\n\nconst apiBaseUrl = (): string => (process.env.GIGADRIVE_API_URL ?? 'https://api.gigadrive.network').replace(/\\/$/, '');\n\nconst encodeBinary = (value: unknown, seen = new WeakSet<object>()): unknown => {\n if (value instanceof Uint8Array) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n if (value instanceof ArrayBuffer) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n // Next stores App Router RSC segment payloads as a `Map<string, Buffer>`\n // (`segmentData`). `Object.entries` on a Map yields nothing, so without an\n // explicit branch the whole map would serialize to `{}` and every prefetched\n // segment would be silently lost on the next read.\n if (value instanceof Map) {\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const entries = [...value.entries()].map(([key, item]) => [encodeBinary(key, seen), encodeBinary(item, seen)]);\n seen.delete(value);\n return { __gigadriveType: 'map', value: entries };\n }\n if (Array.isArray(value)) return value.map((item) => encodeBinary(item, seen));\n if (typeof value !== 'object' || value === null) return value;\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) result[key] = encodeBinary(item, seen);\n seen.delete(value);\n return result;\n};\n\nconst decodeBinary = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(decodeBinary);\n if (typeof value !== 'object' || value === null) return value;\n const record = value as Record<string, unknown>;\n if (record.__gigadriveType === 'bytes' && typeof record.value === 'string')\n return Buffer.from(record.value, 'base64');\n if (record.__gigadriveType === 'map' && Array.isArray(record.value)) {\n return new Map(\n (record.value as unknown[]).map((entry) => {\n const [key, item] = entry as [unknown, unknown];\n return [decodeBinary(key), decodeBinary(item)];\n })\n );\n }\n return Object.fromEntries(Object.entries(record).map(([key, item]) => [key, decodeBinary(item)]));\n};\n\nconst getAccessToken = async (): Promise<string> => {\n if (cachedToken && cachedToken.expiresAt > Date.now() + 30_000) return cachedToken.value;\n const clientId = process.env.GIGADRIVE_CLIENT_ID;\n const clientSecret = process.env.GIGADRIVE_CLIENT_SECRET;\n if (!clientId || !clientSecret) throw new Error('Gigadrive workload credentials are unavailable');\n\n const response = await fetch(`${apiBaseUrl()}/oauth2/token`, {\n method: 'POST',\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,\n 'content-type': 'application/x-www-form-urlencoded',\n },\n body: 'grant_type=client_credentials',\n });\n if (!response.ok) throw new Error(`Gigadrive workload authentication failed with status ${response.status}`);\n const token = (await response.json()) as AccessTokenResponse;\n if (!token.access_token) throw new Error('Gigadrive workload authentication returned no access token');\n cachedToken = {\n value: token.access_token,\n expiresAt: Date.now() + Math.max(60, token.expires_in ?? 300) * 1000,\n };\n return token.access_token;\n};\n\nconst request = async (pathname: string, init: RequestInit, attempt = 0): Promise<Response> => {\n const token = await getAccessToken();\n try {\n const response = await fetch(`${apiBaseUrl()}${pathname}`, {\n ...init,\n headers: {\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n 'x-gigadrive-deployment-id': process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? '',\n 'x-gigadrive-build-id': process.env.NEXT_BUILD_ID ?? '',\n ...init.headers,\n },\n });\n if (response.status === 401 && attempt === 0) {\n cachedToken = undefined;\n return request(pathname, init, attempt + 1);\n }\n if (response.status >= 500 && attempt < 2) return request(pathname, init, attempt + 1);\n return response;\n } catch (error) {\n if (attempt < 2) return request(pathname, init, attempt + 1);\n throw error;\n }\n};\n\nconst cachePath = (kind: string, key: string): string =>\n `/internal/runtime-cache/v1/entries/${encodeURIComponent(kind)}/${encodeURIComponent(key)}`;\n\nexport const readRuntimeCache = async (kind: string, key: string): Promise<unknown | undefined> => {\n try {\n const response = await request(cachePath(kind, key), { method: 'GET' });\n if (response.status === 404) return undefined;\n if (!response.ok) return undefined;\n const envelope = (await response.json()) as RuntimeCacheEnvelope;\n return decodeBinary(envelope.value);\n } catch {\n return undefined;\n }\n};\n\nexport const writeRuntimeCache = async (\n kind: string,\n key: string,\n value: unknown,\n tags: readonly string[] = []\n): Promise<void> => {\n const response = await request(cachePath(kind, key), {\n method: 'PUT',\n body: JSON.stringify({ value: encodeBinary(value), tags }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache write failed with status ${response.status}`);\n};\n\nexport const revalidateRuntimeCacheTags = async (\n kind: string,\n tags: readonly string[],\n durations?: { expire?: number }\n): Promise<void> => {\n const response = await request('/internal/runtime-cache/v1/tags/revalidate', {\n method: 'POST',\n body: JSON.stringify({ kind, tags, durations }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache revalidation failed with status ${response.status}`);\n};\n\nexport const getRuntimeCacheTagExpiration = async (kind: string, tags: readonly string[]): Promise<number> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/expiration', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return 0;\n const value = (await response.json()) as { expiration?: unknown };\n return typeof value.expiration === 'number' ? value.expiration : 0;\n } catch {\n return 0;\n }\n};\n\nexport const getRuntimeCacheTagState = async (kind: string, tags: readonly string[]): Promise<RuntimeCacheTagState> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/state', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return { stale: 0, expired: 0 };\n const value = (await response.json()) as { stale?: unknown; expired?: unknown };\n return {\n stale: typeof value.stale === 'number' ? value.stale : 0,\n expired: typeof value.expired === 'number' ? value.expired : 0,\n };\n } catch {\n return { stale: 0, expired: 0 };\n }\n};\n\nexport const resetRuntimeCacheClientForTests = (): void => {\n cachedToken = undefined;\n};\n\n/**\n * Re-establishes the client's network state after a microVM resume.\n *\n * The guest runtime delivers SIGUSR2 when the instance is restored from a\n * suspend snapshot. At that moment every kept-alive TCP connection from before\n * the freeze is dead, and the cached OAuth token may have expired while the\n * clock was stopped. Dropping the token and dialing one throwaway read\n * re-opens TCP+TLS and refreshes the token concurrently with the guest's own\n * wake-up work, so the first real cache read after a resume does not\n * serialize behind reconnection.\n *\n * Registered only when a Gigadrive deployment marker is present in the\n * environment, so local `next dev`/`next build` never gains a signal listener.\n */\nconst registerResumeRewarm = (): void => {\n // The deployment id is intentionally available during `next build`, but the\n // shared cache client is also bundled into Edge routes at that point. Keep\n // every Node-only signal reference behind the build-phase guard so Turbopack\n // can eliminate this branch before its Edge runtime validation runs.\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') return;\n\n const onGigadrive =\n process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;\n if (!onGigadrive) return;\n\n // This module is shared by Node and Edge cache-handler bundles. Next.js 16.2\n // rejects a statically analyzable `process.on` call while collecting Edge\n // route data, even though the listener only runs inside the Node runtime.\n // Resolve the optional Node signal API reflectively so Edge builds can load\n // the shared client while Node deployments retain resume rewarming.\n const runtimeProcess = Reflect.get(globalThis, 'process') as NodeJS.Process | undefined;\n const addSignalListener = runtimeProcess && Reflect.get(runtimeProcess, 'on');\n if (typeof addSignalListener !== 'function') return;\n\n Reflect.apply(addSignalListener, runtimeProcess, [\n 'SIGUSR2',\n () => {\n cachedToken = undefined;\n if (!process.env.GIGADRIVE_CLIENT_ID || !process.env.GIGADRIVE_CLIENT_SECRET) return;\n void readRuntimeCache('warmup', '__resume__');\n },\n ]);\n};\nregisterResumeRewarm();\n","import {\n getRuntimeCacheTagState,\n readRuntimeCache,\n revalidateRuntimeCacheTags,\n writeRuntimeCache,\n} from './nextjs-runtime-cache-client';\n\ninterface CacheComponentEntry {\n value: ReadableStream<Uint8Array>;\n tags: string[];\n stale: number;\n timestamp: number;\n expire: number;\n revalidate: number;\n}\n\ninterface SerializedCacheComponentEntry extends Omit<CacheComponentEntry, 'value'> {\n value: Uint8Array;\n}\n\nconst isSerializedCacheComponentEntry = (value: unknown): value is SerializedCacheComponentEntry => {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Partial<SerializedCacheComponentEntry>;\n return (\n entry.value instanceof Uint8Array &&\n Array.isArray(entry.tags) &&\n entry.tags.every((tag) => typeof tag === 'string') &&\n typeof entry.stale === 'number' &&\n typeof entry.timestamp === 'number' &&\n typeof entry.expire === 'number' &&\n typeof entry.revalidate === 'number'\n );\n};\n\nconst pendingWrites = new Map<string, Promise<void>>();\nconst buildEntries = new Map<string, SerializedCacheComponentEntry>();\n\nconst streamToBytes = async (stream: ReadableStream<Uint8Array>): Promise<Uint8Array> => {\n const chunks: Uint8Array[] = [];\n let size = 0;\n const reader = stream.getReader();\n while (true) {\n const result = await reader.read();\n if (result.done) break;\n chunks.push(result.value);\n size += result.value.byteLength;\n }\n const bytes = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return bytes;\n};\n\n/** Shared Network cache handler for Next.js Cache Components and `use cache`. */\nconst cacheHandler = {\n async get(cacheKey: string, softTags: string[]): Promise<CacheComponentEntry | undefined> {\n await pendingWrites.get(cacheKey);\n const value =\n process.env.GIGADRIVE_NEXT_BUILD === '1'\n ? buildEntries.get(cacheKey)\n : await readRuntimeCache('component', cacheKey);\n if (!isSerializedCacheComponentEntry(value)) return undefined;\n const tagState =\n process.env.GIGADRIVE_NEXT_BUILD === '1'\n ? { stale: 0, expired: 0 }\n : await getRuntimeCacheTagState('component', [...new Set([...value.tags, ...softTags])]);\n if (tagState.expired > value.timestamp) return undefined;\n return {\n ...value,\n ...(tagState.stale > value.timestamp ? { revalidate: -1 } : {}),\n value: new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(value.value);\n controller.close();\n },\n }),\n };\n },\n\n async set(cacheKey: string, pendingEntry: Promise<CacheComponentEntry>): Promise<void> {\n const write = (async () => {\n const entry = await pendingEntry;\n const value = await streamToBytes(entry.value);\n const serializedEntry = { ...entry, value };\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') {\n buildEntries.set(cacheKey, serializedEntry);\n } else {\n await writeRuntimeCache('component', cacheKey, serializedEntry, entry.tags);\n }\n })();\n pendingWrites.set(cacheKey, write);\n try {\n await write;\n } finally {\n if (pendingWrites.get(cacheKey) === write) pendingWrites.delete(cacheKey);\n }\n },\n\n async refreshTags(): Promise<void> {},\n\n getExpiration(): Promise<number> {\n return Promise.resolve(Infinity);\n },\n\n async updateTags(tags: string[], durations?: { expire?: number }): Promise<void> {\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') {\n for (const [key, entry] of buildEntries) {\n if (entry.tags.some((tag) => tags.includes(tag))) buildEntries.delete(key);\n }\n return;\n }\n return revalidateRuntimeCacheTags('component', tags, durations);\n },\n};\n\nexport default cacheHandler;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/nextjs-runtime-cache-client.ts","../src/nextjs-cache-components-handler.ts"],"sourcesContent":["interface RuntimeCacheEnvelope {\n value: unknown;\n}\n\ninterface AccessTokenResponse {\n access_token: string;\n expires_in?: number;\n}\n\nexport interface RuntimeCacheTagState {\n stale: number;\n expired: number;\n}\n\nlet cachedToken: { value: string; expiresAt: number } | undefined;\n\nconst apiBaseUrl = (): string => (process.env.GIGADRIVE_API_URL ?? 'https://api.gigadrive.network').replace(/\\/$/, '');\n\nconst encodeBinary = (value: unknown, seen = new WeakSet<object>()): unknown => {\n if (value instanceof Uint8Array) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n if (value instanceof ArrayBuffer) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n // Next stores App Router RSC segment payloads as a `Map<string, Buffer>`\n // (`segmentData`). `Object.entries` on a Map yields nothing, so without an\n // explicit branch the whole map would serialize to `{}` and every prefetched\n // segment would be silently lost on the next read.\n if (value instanceof Map) {\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const entries = [...value.entries()].map(([key, item]) => [encodeBinary(key, seen), encodeBinary(item, seen)]);\n seen.delete(value);\n return { __gigadriveType: 'map', value: entries };\n }\n if (Array.isArray(value)) return value.map((item) => encodeBinary(item, seen));\n if (typeof value !== 'object' || value === null) return value;\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) result[key] = encodeBinary(item, seen);\n seen.delete(value);\n return result;\n};\n\nconst decodeBinary = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(decodeBinary);\n if (typeof value !== 'object' || value === null) return value;\n const record = value as Record<string, unknown>;\n if (record.__gigadriveType === 'bytes' && typeof record.value === 'string')\n return Buffer.from(record.value, 'base64');\n if (record.__gigadriveType === 'map' && Array.isArray(record.value)) {\n return new Map(\n (record.value as unknown[]).map((entry) => {\n const [key, item] = entry as [unknown, unknown];\n return [decodeBinary(key), decodeBinary(item)];\n })\n );\n }\n return Object.fromEntries(Object.entries(record).map(([key, item]) => [key, decodeBinary(item)]));\n};\n\nconst getAccessToken = async (): Promise<string> => {\n if (cachedToken && cachedToken.expiresAt > Date.now() + 30_000) return cachedToken.value;\n const clientId = process.env.GIGADRIVE_CLIENT_ID;\n const clientSecret = process.env.GIGADRIVE_CLIENT_SECRET;\n if (!clientId || !clientSecret) throw new Error('Gigadrive workload credentials are unavailable');\n\n const response = await fetch(`${apiBaseUrl()}/oauth2/token`, {\n method: 'POST',\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,\n 'content-type': 'application/x-www-form-urlencoded',\n },\n body: 'grant_type=client_credentials',\n });\n if (!response.ok) throw new Error(`Gigadrive workload authentication failed with status ${response.status}`);\n const token = (await response.json()) as AccessTokenResponse;\n if (!token.access_token) throw new Error('Gigadrive workload authentication returned no access token');\n cachedToken = {\n value: token.access_token,\n expiresAt: Date.now() + Math.max(60, token.expires_in ?? 300) * 1000,\n };\n return token.access_token;\n};\n\nconst request = async (pathname: string, init: RequestInit, attempt = 0): Promise<Response> => {\n const token = await getAccessToken();\n try {\n const response = await fetch(`${apiBaseUrl()}${pathname}`, {\n ...init,\n headers: {\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n 'x-gigadrive-deployment-id': process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? '',\n 'x-gigadrive-build-id': process.env.NEXT_BUILD_ID ?? '',\n ...init.headers,\n },\n });\n if (response.status === 401 && attempt === 0) {\n cachedToken = undefined;\n return request(pathname, init, attempt + 1);\n }\n if (response.status >= 500 && attempt < 2) return request(pathname, init, attempt + 1);\n return response;\n } catch (error) {\n if (attempt < 2) return request(pathname, init, attempt + 1);\n throw error;\n }\n};\n\nconst cachePath = (kind: string, key: string): string =>\n `/internal/runtime-cache/v1/entries/${encodeURIComponent(kind)}/${encodeURIComponent(key)}`;\n\nexport const readRuntimeCache = async (kind: string, key: string): Promise<unknown | undefined> => {\n try {\n const response = await request(cachePath(kind, key), { method: 'GET' });\n if (response.status === 404) return undefined;\n if (!response.ok) return undefined;\n const envelope = (await response.json()) as RuntimeCacheEnvelope;\n return decodeBinary(envelope.value);\n } catch {\n return undefined;\n }\n};\n\nexport const writeRuntimeCache = async (\n kind: string,\n key: string,\n value: unknown,\n tags: readonly string[] = []\n): Promise<void> => {\n const response = await request(cachePath(kind, key), {\n method: 'PUT',\n body: JSON.stringify({ value: encodeBinary(value), tags }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache write failed with status ${response.status}`);\n};\n\nexport const revalidateRuntimeCacheTags = async (\n kind: string,\n tags: readonly string[],\n durations?: { expire?: number }\n): Promise<void> => {\n const response = await request('/internal/runtime-cache/v1/tags/revalidate', {\n method: 'POST',\n body: JSON.stringify({ kind, tags, durations }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache revalidation failed with status ${response.status}`);\n};\n\nexport const getRuntimeCacheTagExpiration = async (kind: string, tags: readonly string[]): Promise<number> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/expiration', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return 0;\n const value = (await response.json()) as { expiration?: unknown };\n return typeof value.expiration === 'number' ? value.expiration : 0;\n } catch {\n return 0;\n }\n};\n\nexport const getRuntimeCacheTagState = async (kind: string, tags: readonly string[]): Promise<RuntimeCacheTagState> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/state', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return { stale: 0, expired: 0 };\n const value = (await response.json()) as { stale?: unknown; expired?: unknown };\n return {\n stale: typeof value.stale === 'number' ? value.stale : 0,\n expired: typeof value.expired === 'number' ? value.expired : 0,\n };\n } catch {\n return { stale: 0, expired: 0 };\n }\n};\n\nexport const resetRuntimeCacheClientForTests = (): void => {\n cachedToken = undefined;\n};\n\n/**\n * Re-establishes the client's network state after a microVM resume.\n *\n * The guest runtime delivers SIGUSR2 when the instance is restored from a\n * suspend snapshot. At that moment every kept-alive TCP connection from before\n * the freeze is dead, and the cached OAuth token may have expired while the\n * clock was stopped. Dropping the token and dialing one throwaway read\n * re-opens TCP+TLS and refreshes the token concurrently with the guest's own\n * wake-up work, so the first real cache read after a resume does not\n * serialize behind reconnection.\n *\n * Registered only when a Gigadrive deployment marker is present in the\n * environment, so local `next dev`/`next build` never gains a signal listener.\n */\nconst registerResumeRewarm = (): void => {\n // Next exposes this marker before evaluating an Edge route bundle. Bail out\n // before touching `process`: its Edge compatibility proxy throws when the\n // Node-only signal API is read, including through Reflect.\n if (Reflect.has(globalThis, 'EdgeRuntime')) return;\n\n // The deployment id is intentionally available during `next build`, but the\n // shared cache client is also bundled into Edge routes at that point. Keep\n // every Node-only signal reference behind the build-phase guard so Turbopack\n // can eliminate this branch before its Edge runtime validation runs.\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') return;\n\n const onGigadrive =\n process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;\n if (!onGigadrive) return;\n\n // Resolve the optional Node signal API reflectively so non-Node runtimes can\n // load the shared client while Node deployments retain resume rewarming.\n const runtimeProcess = Reflect.get(globalThis, 'process') as NodeJS.Process | undefined;\n const addSignalListener = runtimeProcess && Reflect.get(runtimeProcess, 'on');\n if (typeof addSignalListener !== 'function') return;\n\n Reflect.apply(addSignalListener, runtimeProcess, [\n 'SIGUSR2',\n () => {\n cachedToken = undefined;\n if (!process.env.GIGADRIVE_CLIENT_ID || !process.env.GIGADRIVE_CLIENT_SECRET) return;\n void readRuntimeCache('warmup', '__resume__');\n },\n ]);\n};\nregisterResumeRewarm();\n","import {\n getRuntimeCacheTagState,\n readRuntimeCache,\n revalidateRuntimeCacheTags,\n writeRuntimeCache,\n} from './nextjs-runtime-cache-client';\n\ninterface CacheComponentEntry {\n value: ReadableStream<Uint8Array>;\n tags: string[];\n stale: number;\n timestamp: number;\n expire: number;\n revalidate: number;\n}\n\ninterface SerializedCacheComponentEntry extends Omit<CacheComponentEntry, 'value'> {\n value: Uint8Array;\n}\n\nconst isSerializedCacheComponentEntry = (value: unknown): value is SerializedCacheComponentEntry => {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Partial<SerializedCacheComponentEntry>;\n return (\n entry.value instanceof Uint8Array &&\n Array.isArray(entry.tags) &&\n entry.tags.every((tag) => typeof tag === 'string') &&\n typeof entry.stale === 'number' &&\n typeof entry.timestamp === 'number' &&\n typeof entry.expire === 'number' &&\n typeof entry.revalidate === 'number'\n );\n};\n\nconst pendingWrites = new Map<string, Promise<void>>();\nconst buildEntries = new Map<string, SerializedCacheComponentEntry>();\n\nconst streamToBytes = async (stream: ReadableStream<Uint8Array>): Promise<Uint8Array> => {\n const chunks: Uint8Array[] = [];\n let size = 0;\n const reader = stream.getReader();\n while (true) {\n const result = await reader.read();\n if (result.done) break;\n chunks.push(result.value);\n size += result.value.byteLength;\n }\n const bytes = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return bytes;\n};\n\n/** Shared Network cache handler for Next.js Cache Components and `use cache`. */\nconst cacheHandler = {\n async get(cacheKey: string, softTags: string[]): Promise<CacheComponentEntry | undefined> {\n await pendingWrites.get(cacheKey);\n const value =\n process.env.GIGADRIVE_NEXT_BUILD === '1'\n ? buildEntries.get(cacheKey)\n : await readRuntimeCache('component', cacheKey);\n if (!isSerializedCacheComponentEntry(value)) return undefined;\n const tagState =\n process.env.GIGADRIVE_NEXT_BUILD === '1'\n ? { stale: 0, expired: 0 }\n : await getRuntimeCacheTagState('component', [...new Set([...value.tags, ...softTags])]);\n if (tagState.expired > value.timestamp) return undefined;\n return {\n ...value,\n ...(tagState.stale > value.timestamp ? { revalidate: -1 } : {}),\n value: new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(value.value);\n controller.close();\n },\n }),\n };\n },\n\n async set(cacheKey: string, pendingEntry: Promise<CacheComponentEntry>): Promise<void> {\n const write = (async () => {\n const entry = await pendingEntry;\n const value = await streamToBytes(entry.value);\n const serializedEntry = { ...entry, value };\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') {\n buildEntries.set(cacheKey, serializedEntry);\n } else {\n await writeRuntimeCache('component', cacheKey, serializedEntry, entry.tags);\n }\n })();\n pendingWrites.set(cacheKey, write);\n try {\n await write;\n } finally {\n if (pendingWrites.get(cacheKey) === write) pendingWrites.delete(cacheKey);\n }\n },\n\n async refreshTags(): Promise<void> {},\n\n getExpiration(): Promise<number> {\n return Promise.resolve(Infinity);\n },\n\n async updateTags(tags: string[], durations?: { expire?: number }): Promise<void> {\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') {\n for (const [key, entry] of buildEntries) {\n if (entry.tags.some((tag) => tags.includes(tag))) buildEntries.delete(key);\n }\n return;\n }\n return revalidateRuntimeCacheTags('component', tags, durations);\n },\n};\n\nexport default cacheHandler;\n"],"mappings":"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","names":[]}
|
|
@@ -166,6 +166,7 @@ var getRuntimeCacheTagState = async (kind, tags) => {
|
|
|
166
166
|
}
|
|
167
167
|
};
|
|
168
168
|
var registerResumeRewarm = () => {
|
|
169
|
+
if (Reflect.has(globalThis, "EdgeRuntime")) return;
|
|
169
170
|
if (process.env.GIGADRIVE_NEXT_BUILD === "1") return;
|
|
170
171
|
const onGigadrive = process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;
|
|
171
172
|
if (!onGigadrive) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nextjs-cache-handler.ts","../src/nextjs-runtime-cache-client.ts"],"sourcesContent":["import {\n getRuntimeCacheTagState,\n readRuntimeCache,\n revalidateRuntimeCacheTags,\n writeRuntimeCache,\n} from './nextjs-runtime-cache-client';\n\n/** Header Next uses to carry an entry's cache tags (comma separated). */\nconst NEXT_CACHE_TAGS_HEADER = 'x-next-cache-tags';\n\ninterface IncrementalCacheContext {\n tags?: string[];\n softTags?: string[];\n cacheControl?: unknown;\n kind?: string;\n}\n\ninterface IncrementalCacheEntry {\n lastModified: number;\n value: unknown | null;\n tags?: string[];\n cacheControl?: unknown;\n}\n\n/** Constructor context Next passes to a custom cache handler. */\ninterface CacheHandlerConstructorContext {\n fs?: unknown;\n serverDistDir?: string;\n dev?: boolean;\n flushToDisk?: boolean;\n revalidatedTags?: string[];\n maxMemoryCacheSize?: number;\n _requestHeaders?: unknown;\n fetchCacheKeyPrefix?: string;\n}\n\ninterface FileSystemCacheLike {\n get(key: string, context: IncrementalCacheContext): Promise<IncrementalCacheEntry | null | undefined>;\n}\n\nconst isIncrementalCacheEntry = (value: unknown): value is IncrementalCacheEntry =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<IncrementalCacheEntry>).lastModified === 'number' &&\n 'value' in value;\n\n/**\n * Reads the cache tags carried by a cached value's own headers.\n *\n * Next never populates `context.tags` for APP_PAGE/APP_ROUTE/PAGES — only fetch\n * cache entries carry tags on the context. For route entries the tags live in\n * the cached value's headers under `x-next-cache-tags` as a comma-joined string,\n * so reading them here is what keeps the remote tag index (and therefore\n * `revalidateTag`) working for pages and route handlers.\n */\nconst valueTags = (value: unknown): string[] => {\n const header = (value as { headers?: Record<string, unknown> } | null)?.headers?.[NEXT_CACHE_TAGS_HEADER];\n if (typeof header !== 'string') return [];\n return header\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean);\n};\n\n/** Every tag relevant to an entry: its own, the request's, and the value's headers. */\nconst collectTags = (\n entryTags: string[] | undefined,\n value: unknown,\n context: IncrementalCacheContext = {}\n): string[] => [\n ...new Set([...(entryTags ?? []), ...(context.tags ?? []), ...(context.softTags ?? []), ...valueTags(value)]),\n];\n\nconst isBuildPhase = (): boolean => process.env.GIGADRIVE_NEXT_BUILD === '1';\n\n/**\n * How long a locally cached entry may serve before the remote copy is re-read.\n * Bounds staleness when another instance rewrites the entry; tag-driven\n * invalidation is unaffected because tag state is checked remotely on every\n * read regardless of where the entry bytes came from.\n */\nconst LOCAL_ENTRY_TTL_MS = 5 * 60_000;\nconst LOCAL_CACHE_MAX_ENTRIES = 256;\nconst LOCAL_CACHE_MAX_TOTAL_BYTES = 64 * 1024 * 1024;\nconst LOCAL_CACHE_MAX_ENTRY_BYTES = 8 * 1024 * 1024;\n\ninterface LocalCacheSlot {\n entry: IncrementalCacheEntry;\n cachedAt: number;\n bytes: number;\n}\n\nconst approximateEntryBytes = (entry: IncrementalCacheEntry): number => {\n try {\n return JSON.stringify(entry)?.length ?? LOCAL_CACHE_MAX_ENTRY_BYTES + 1;\n } catch {\n // Circular or otherwise unserializable values are never cached locally.\n return LOCAL_CACHE_MAX_ENTRY_BYTES + 1;\n }\n};\n\n/**\n * Byte-bounded in-process LRU in front of the remote entry store.\n *\n * The remote store is an HTTP service backed by object storage, so every miss\n * costs a network round trip — and when that store degrades, page renders\n * degrade with it (a production incident showed second-level blob latency\n * turning every render of a cached page into a multi-second response).\n * Serving entry bytes locally removes that dependency from the hot path while\n * the per-read remote tag-state check keeps `revalidateTag` authoritative.\n */\nclass LocalEntryCache {\n private readonly slots = new Map<string, LocalCacheSlot>();\n private totalBytes = 0;\n\n get(key: string): IncrementalCacheEntry | undefined {\n const slot = this.slots.get(key);\n if (!slot) return undefined;\n if (Date.now() - slot.cachedAt > LOCAL_ENTRY_TTL_MS) {\n this.delete(key);\n return undefined;\n }\n // Refresh recency for LRU eviction.\n this.slots.delete(key);\n this.slots.set(key, slot);\n return slot.entry;\n }\n\n set(key: string, entry: IncrementalCacheEntry): void {\n const bytes = approximateEntryBytes(entry);\n if (bytes > LOCAL_CACHE_MAX_ENTRY_BYTES) {\n this.delete(key);\n return;\n }\n this.delete(key);\n this.slots.set(key, { entry, cachedAt: Date.now(), bytes });\n this.totalBytes += bytes;\n while (this.slots.size > LOCAL_CACHE_MAX_ENTRIES || this.totalBytes > LOCAL_CACHE_MAX_TOTAL_BYTES) {\n const oldest = this.slots.keys().next().value;\n if (oldest === undefined) break;\n this.delete(oldest);\n }\n }\n\n delete(key: string): void {\n const slot = this.slots.get(key);\n if (!slot) return;\n this.slots.delete(key);\n this.totalBytes -= slot.bytes;\n }\n\n clear(): void {\n this.slots.clear();\n this.totalBytes = 0;\n }\n}\n\nconst localEntries = new LocalEntryCache();\n\n/** Test-only: the local entry cache is process-wide, so suites must isolate it. */\nexport const clearLocalEntryCacheForTesting = (): void => localEntries.clear();\n\n/** Shared Network cache handler for ISR, server responses, fetches, and image metadata. */\nexport default class GigadriveNextCacheHandler {\n private readonly buildEntries = new Map<string, IncrementalCacheEntry>();\n /**\n * Next's own on-disk reader, pointed at the build output that ships inside the\n * deployment bundle (`writeStandaloneDirectory` recursively copies\n * `.next/server/{app,pages}`). Injecting a `cacheHandler` replaces Next's\n * FileSystemCache outright, which would otherwise strand every build-time\n * prerender and force a cold re-render of each page on first request.\n * Delegating to Next's reader keeps us off its private on-disk format.\n */\n private buildOutputCache?: Promise<FileSystemCacheLike | undefined>;\n private readonly context: CacheHandlerConstructorContext;\n\n constructor(context: CacheHandlerConstructorContext = {}) {\n this.context = context;\n }\n\n /**\n * Loads Next's on-disk reader lazily, memoized across requests. A Next release\n * that moves or renames the module degrades to \"no build-output fallback\" —\n * the remote cache still serves everything that has been regenerated.\n */\n private loadBuildOutputCache(): Promise<FileSystemCacheLike | undefined> {\n this.buildOutputCache ??= (async () => {\n if (!this.context.fs || !this.context.serverDistDir) return undefined;\n try {\n const module: unknown = await import('next/dist/server/lib/incremental-cache/file-system-cache.js');\n // Next ships this as CommonJS, so the constructor sits behind a different\n // number of `default` hops depending on whether this bundle was loaded as\n // CJS or ESM. Unwrap until a callable turns up rather than guessing.\n let candidate: unknown = module;\n for (let hop = 0; hop < 3 && candidate && typeof candidate !== 'function'; hop += 1) {\n candidate = (candidate as { default?: unknown }).default;\n }\n if (typeof candidate !== 'function') return undefined;\n const FileSystemCache = candidate as new (context: CacheHandlerConstructorContext) => FileSystemCacheLike;\n return new FileSystemCache(this.context);\n } catch {\n return undefined;\n }\n })();\n return this.buildOutputCache;\n }\n\n /**\n * Applies remote tag state to an entry.\n *\n * @returns the entry, a stale-marked copy, or `null` when a tag expired.\n */\n private async applyTagState(entry: IncrementalCacheEntry, tags: string[]): Promise<IncrementalCacheEntry | null> {\n if (tags.length === 0) return entry;\n const tagState = await getRuntimeCacheTagState('incremental', tags);\n if (tagState.expired > entry.lastModified) return null;\n return tagState.stale > entry.lastModified ? { ...entry, lastModified: 1 } : entry;\n }\n\n async get(key: string, context: IncrementalCacheContext = {}): Promise<IncrementalCacheEntry | null> {\n if (isBuildPhase()) {\n const buildEntry = this.buildEntries.get(key) ?? null;\n return isIncrementalCacheEntry(buildEntry) ? buildEntry : null;\n }\n\n const local = localEntries.get(key);\n if (local) {\n return this.applyTagState(local, collectTags(local.tags, local.value, context));\n }\n\n const remote = await readRuntimeCache('incremental', key);\n if (isIncrementalCacheEntry(remote)) {\n localEntries.set(key, remote);\n return this.applyTagState(remote, collectTags(remote.tags, remote.value, context));\n }\n\n // Nothing regenerated yet: fall back to the build-time prerender shipped in\n // the bundle. Tag expiry is still resolved against the remote index — Next's\n // reader only knows its own in-process tag manifest, which is always empty\n // here, so trusting it would resurrect content after a `revalidateTag`.\n const buildOutputCache = await this.loadBuildOutputCache();\n const fromDisk = await buildOutputCache?.get(key, context).catch(() => null);\n if (!isIncrementalCacheEntry(fromDisk)) return null;\n return this.applyTagState(fromDisk, collectTags(fromDisk.tags, fromDisk.value, context));\n }\n\n async set(key: string, data: unknown, context: IncrementalCacheContext): Promise<void> {\n const tags = collectTags(undefined, data, context);\n const entry = { lastModified: Date.now(), value: data, tags, cacheControl: context.cacheControl };\n if (isBuildPhase()) {\n this.buildEntries.set(key, entry);\n return;\n }\n localEntries.set(key, entry);\n try {\n await writeRuntimeCache('incremental', key, entry, tags);\n } catch (error) {\n // The local copy would outlive a failed durable write and mask it from\n // this instance for the whole TTL; drop it so reads retry remotely.\n localEntries.delete(key);\n throw error;\n }\n }\n\n async revalidateTag(tags: string | string[], durations?: { expire?: number }): Promise<void> {\n const normalizedTags = Array.isArray(tags) ? tags : [tags];\n if (isBuildPhase()) {\n for (const [key, entry] of this.buildEntries) {\n if (entry.tags?.some((tag) => normalizedTags.includes(tag))) this.buildEntries.delete(key);\n }\n return;\n }\n await revalidateRuntimeCacheTags('incremental', normalizedTags, durations);\n }\n\n resetRequestCache(): void {}\n}\n","interface RuntimeCacheEnvelope {\n value: unknown;\n}\n\ninterface AccessTokenResponse {\n access_token: string;\n expires_in?: number;\n}\n\nexport interface RuntimeCacheTagState {\n stale: number;\n expired: number;\n}\n\nlet cachedToken: { value: string; expiresAt: number } | undefined;\n\nconst apiBaseUrl = (): string => (process.env.GIGADRIVE_API_URL ?? 'https://api.gigadrive.network').replace(/\\/$/, '');\n\nconst encodeBinary = (value: unknown, seen = new WeakSet<object>()): unknown => {\n if (value instanceof Uint8Array) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n if (value instanceof ArrayBuffer) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n // Next stores App Router RSC segment payloads as a `Map<string, Buffer>`\n // (`segmentData`). `Object.entries` on a Map yields nothing, so without an\n // explicit branch the whole map would serialize to `{}` and every prefetched\n // segment would be silently lost on the next read.\n if (value instanceof Map) {\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const entries = [...value.entries()].map(([key, item]) => [encodeBinary(key, seen), encodeBinary(item, seen)]);\n seen.delete(value);\n return { __gigadriveType: 'map', value: entries };\n }\n if (Array.isArray(value)) return value.map((item) => encodeBinary(item, seen));\n if (typeof value !== 'object' || value === null) return value;\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) result[key] = encodeBinary(item, seen);\n seen.delete(value);\n return result;\n};\n\nconst decodeBinary = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(decodeBinary);\n if (typeof value !== 'object' || value === null) return value;\n const record = value as Record<string, unknown>;\n if (record.__gigadriveType === 'bytes' && typeof record.value === 'string')\n return Buffer.from(record.value, 'base64');\n if (record.__gigadriveType === 'map' && Array.isArray(record.value)) {\n return new Map(\n (record.value as unknown[]).map((entry) => {\n const [key, item] = entry as [unknown, unknown];\n return [decodeBinary(key), decodeBinary(item)];\n })\n );\n }\n return Object.fromEntries(Object.entries(record).map(([key, item]) => [key, decodeBinary(item)]));\n};\n\nconst getAccessToken = async (): Promise<string> => {\n if (cachedToken && cachedToken.expiresAt > Date.now() + 30_000) return cachedToken.value;\n const clientId = process.env.GIGADRIVE_CLIENT_ID;\n const clientSecret = process.env.GIGADRIVE_CLIENT_SECRET;\n if (!clientId || !clientSecret) throw new Error('Gigadrive workload credentials are unavailable');\n\n const response = await fetch(`${apiBaseUrl()}/oauth2/token`, {\n method: 'POST',\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,\n 'content-type': 'application/x-www-form-urlencoded',\n },\n body: 'grant_type=client_credentials',\n });\n if (!response.ok) throw new Error(`Gigadrive workload authentication failed with status ${response.status}`);\n const token = (await response.json()) as AccessTokenResponse;\n if (!token.access_token) throw new Error('Gigadrive workload authentication returned no access token');\n cachedToken = {\n value: token.access_token,\n expiresAt: Date.now() + Math.max(60, token.expires_in ?? 300) * 1000,\n };\n return token.access_token;\n};\n\nconst request = async (pathname: string, init: RequestInit, attempt = 0): Promise<Response> => {\n const token = await getAccessToken();\n try {\n const response = await fetch(`${apiBaseUrl()}${pathname}`, {\n ...init,\n headers: {\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n 'x-gigadrive-deployment-id': process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? '',\n 'x-gigadrive-build-id': process.env.NEXT_BUILD_ID ?? '',\n ...init.headers,\n },\n });\n if (response.status === 401 && attempt === 0) {\n cachedToken = undefined;\n return request(pathname, init, attempt + 1);\n }\n if (response.status >= 500 && attempt < 2) return request(pathname, init, attempt + 1);\n return response;\n } catch (error) {\n if (attempt < 2) return request(pathname, init, attempt + 1);\n throw error;\n }\n};\n\nconst cachePath = (kind: string, key: string): string =>\n `/internal/runtime-cache/v1/entries/${encodeURIComponent(kind)}/${encodeURIComponent(key)}`;\n\nexport const readRuntimeCache = async (kind: string, key: string): Promise<unknown | undefined> => {\n try {\n const response = await request(cachePath(kind, key), { method: 'GET' });\n if (response.status === 404) return undefined;\n if (!response.ok) return undefined;\n const envelope = (await response.json()) as RuntimeCacheEnvelope;\n return decodeBinary(envelope.value);\n } catch {\n return undefined;\n }\n};\n\nexport const writeRuntimeCache = async (\n kind: string,\n key: string,\n value: unknown,\n tags: readonly string[] = []\n): Promise<void> => {\n const response = await request(cachePath(kind, key), {\n method: 'PUT',\n body: JSON.stringify({ value: encodeBinary(value), tags }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache write failed with status ${response.status}`);\n};\n\nexport const revalidateRuntimeCacheTags = async (\n kind: string,\n tags: readonly string[],\n durations?: { expire?: number }\n): Promise<void> => {\n const response = await request('/internal/runtime-cache/v1/tags/revalidate', {\n method: 'POST',\n body: JSON.stringify({ kind, tags, durations }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache revalidation failed with status ${response.status}`);\n};\n\nexport const getRuntimeCacheTagExpiration = async (kind: string, tags: readonly string[]): Promise<number> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/expiration', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return 0;\n const value = (await response.json()) as { expiration?: unknown };\n return typeof value.expiration === 'number' ? value.expiration : 0;\n } catch {\n return 0;\n }\n};\n\nexport const getRuntimeCacheTagState = async (kind: string, tags: readonly string[]): Promise<RuntimeCacheTagState> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/state', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return { stale: 0, expired: 0 };\n const value = (await response.json()) as { stale?: unknown; expired?: unknown };\n return {\n stale: typeof value.stale === 'number' ? value.stale : 0,\n expired: typeof value.expired === 'number' ? value.expired : 0,\n };\n } catch {\n return { stale: 0, expired: 0 };\n }\n};\n\nexport const resetRuntimeCacheClientForTests = (): void => {\n cachedToken = undefined;\n};\n\n/**\n * Re-establishes the client's network state after a microVM resume.\n *\n * The guest runtime delivers SIGUSR2 when the instance is restored from a\n * suspend snapshot. At that moment every kept-alive TCP connection from before\n * the freeze is dead, and the cached OAuth token may have expired while the\n * clock was stopped. Dropping the token and dialing one throwaway read\n * re-opens TCP+TLS and refreshes the token concurrently with the guest's own\n * wake-up work, so the first real cache read after a resume does not\n * serialize behind reconnection.\n *\n * Registered only when a Gigadrive deployment marker is present in the\n * environment, so local `next dev`/`next build` never gains a signal listener.\n */\nconst registerResumeRewarm = (): void => {\n // The deployment id is intentionally available during `next build`, but the\n // shared cache client is also bundled into Edge routes at that point. Keep\n // every Node-only signal reference behind the build-phase guard so Turbopack\n // can eliminate this branch before its Edge runtime validation runs.\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') return;\n\n const onGigadrive =\n process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;\n if (!onGigadrive) return;\n\n // This module is shared by Node and Edge cache-handler bundles. Next.js 16.2\n // rejects a statically analyzable `process.on` call while collecting Edge\n // route data, even though the listener only runs inside the Node runtime.\n // Resolve the optional Node signal API reflectively so Edge builds can load\n // the shared client while Node deployments retain resume rewarming.\n const runtimeProcess = Reflect.get(globalThis, 'process') as NodeJS.Process | undefined;\n const addSignalListener = runtimeProcess && Reflect.get(runtimeProcess, 'on');\n if (typeof addSignalListener !== 'function') return;\n\n Reflect.apply(addSignalListener, runtimeProcess, [\n 'SIGUSR2',\n () => {\n cachedToken = undefined;\n if (!process.env.GIGADRIVE_CLIENT_ID || !process.env.GIGADRIVE_CLIENT_SECRET) return;\n void readRuntimeCache('warmup', '__resume__');\n },\n ]);\n};\nregisterResumeRewarm();\n"],"mappings":"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","names":["module"]}
|
|
1
|
+
{"version":3,"sources":["../src/nextjs-cache-handler.ts","../src/nextjs-runtime-cache-client.ts"],"sourcesContent":["import {\n getRuntimeCacheTagState,\n readRuntimeCache,\n revalidateRuntimeCacheTags,\n writeRuntimeCache,\n} from './nextjs-runtime-cache-client';\n\n/** Header Next uses to carry an entry's cache tags (comma separated). */\nconst NEXT_CACHE_TAGS_HEADER = 'x-next-cache-tags';\n\ninterface IncrementalCacheContext {\n tags?: string[];\n softTags?: string[];\n cacheControl?: unknown;\n kind?: string;\n}\n\ninterface IncrementalCacheEntry {\n lastModified: number;\n value: unknown | null;\n tags?: string[];\n cacheControl?: unknown;\n}\n\n/** Constructor context Next passes to a custom cache handler. */\ninterface CacheHandlerConstructorContext {\n fs?: unknown;\n serverDistDir?: string;\n dev?: boolean;\n flushToDisk?: boolean;\n revalidatedTags?: string[];\n maxMemoryCacheSize?: number;\n _requestHeaders?: unknown;\n fetchCacheKeyPrefix?: string;\n}\n\ninterface FileSystemCacheLike {\n get(key: string, context: IncrementalCacheContext): Promise<IncrementalCacheEntry | null | undefined>;\n}\n\nconst isIncrementalCacheEntry = (value: unknown): value is IncrementalCacheEntry =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<IncrementalCacheEntry>).lastModified === 'number' &&\n 'value' in value;\n\n/**\n * Reads the cache tags carried by a cached value's own headers.\n *\n * Next never populates `context.tags` for APP_PAGE/APP_ROUTE/PAGES — only fetch\n * cache entries carry tags on the context. For route entries the tags live in\n * the cached value's headers under `x-next-cache-tags` as a comma-joined string,\n * so reading them here is what keeps the remote tag index (and therefore\n * `revalidateTag`) working for pages and route handlers.\n */\nconst valueTags = (value: unknown): string[] => {\n const header = (value as { headers?: Record<string, unknown> } | null)?.headers?.[NEXT_CACHE_TAGS_HEADER];\n if (typeof header !== 'string') return [];\n return header\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean);\n};\n\n/** Every tag relevant to an entry: its own, the request's, and the value's headers. */\nconst collectTags = (\n entryTags: string[] | undefined,\n value: unknown,\n context: IncrementalCacheContext = {}\n): string[] => [\n ...new Set([...(entryTags ?? []), ...(context.tags ?? []), ...(context.softTags ?? []), ...valueTags(value)]),\n];\n\nconst isBuildPhase = (): boolean => process.env.GIGADRIVE_NEXT_BUILD === '1';\n\n/**\n * How long a locally cached entry may serve before the remote copy is re-read.\n * Bounds staleness when another instance rewrites the entry; tag-driven\n * invalidation is unaffected because tag state is checked remotely on every\n * read regardless of where the entry bytes came from.\n */\nconst LOCAL_ENTRY_TTL_MS = 5 * 60_000;\nconst LOCAL_CACHE_MAX_ENTRIES = 256;\nconst LOCAL_CACHE_MAX_TOTAL_BYTES = 64 * 1024 * 1024;\nconst LOCAL_CACHE_MAX_ENTRY_BYTES = 8 * 1024 * 1024;\n\ninterface LocalCacheSlot {\n entry: IncrementalCacheEntry;\n cachedAt: number;\n bytes: number;\n}\n\nconst approximateEntryBytes = (entry: IncrementalCacheEntry): number => {\n try {\n return JSON.stringify(entry)?.length ?? LOCAL_CACHE_MAX_ENTRY_BYTES + 1;\n } catch {\n // Circular or otherwise unserializable values are never cached locally.\n return LOCAL_CACHE_MAX_ENTRY_BYTES + 1;\n }\n};\n\n/**\n * Byte-bounded in-process LRU in front of the remote entry store.\n *\n * The remote store is an HTTP service backed by object storage, so every miss\n * costs a network round trip — and when that store degrades, page renders\n * degrade with it (a production incident showed second-level blob latency\n * turning every render of a cached page into a multi-second response).\n * Serving entry bytes locally removes that dependency from the hot path while\n * the per-read remote tag-state check keeps `revalidateTag` authoritative.\n */\nclass LocalEntryCache {\n private readonly slots = new Map<string, LocalCacheSlot>();\n private totalBytes = 0;\n\n get(key: string): IncrementalCacheEntry | undefined {\n const slot = this.slots.get(key);\n if (!slot) return undefined;\n if (Date.now() - slot.cachedAt > LOCAL_ENTRY_TTL_MS) {\n this.delete(key);\n return undefined;\n }\n // Refresh recency for LRU eviction.\n this.slots.delete(key);\n this.slots.set(key, slot);\n return slot.entry;\n }\n\n set(key: string, entry: IncrementalCacheEntry): void {\n const bytes = approximateEntryBytes(entry);\n if (bytes > LOCAL_CACHE_MAX_ENTRY_BYTES) {\n this.delete(key);\n return;\n }\n this.delete(key);\n this.slots.set(key, { entry, cachedAt: Date.now(), bytes });\n this.totalBytes += bytes;\n while (this.slots.size > LOCAL_CACHE_MAX_ENTRIES || this.totalBytes > LOCAL_CACHE_MAX_TOTAL_BYTES) {\n const oldest = this.slots.keys().next().value;\n if (oldest === undefined) break;\n this.delete(oldest);\n }\n }\n\n delete(key: string): void {\n const slot = this.slots.get(key);\n if (!slot) return;\n this.slots.delete(key);\n this.totalBytes -= slot.bytes;\n }\n\n clear(): void {\n this.slots.clear();\n this.totalBytes = 0;\n }\n}\n\nconst localEntries = new LocalEntryCache();\n\n/** Test-only: the local entry cache is process-wide, so suites must isolate it. */\nexport const clearLocalEntryCacheForTesting = (): void => localEntries.clear();\n\n/** Shared Network cache handler for ISR, server responses, fetches, and image metadata. */\nexport default class GigadriveNextCacheHandler {\n private readonly buildEntries = new Map<string, IncrementalCacheEntry>();\n /**\n * Next's own on-disk reader, pointed at the build output that ships inside the\n * deployment bundle (`writeStandaloneDirectory` recursively copies\n * `.next/server/{app,pages}`). Injecting a `cacheHandler` replaces Next's\n * FileSystemCache outright, which would otherwise strand every build-time\n * prerender and force a cold re-render of each page on first request.\n * Delegating to Next's reader keeps us off its private on-disk format.\n */\n private buildOutputCache?: Promise<FileSystemCacheLike | undefined>;\n private readonly context: CacheHandlerConstructorContext;\n\n constructor(context: CacheHandlerConstructorContext = {}) {\n this.context = context;\n }\n\n /**\n * Loads Next's on-disk reader lazily, memoized across requests. A Next release\n * that moves or renames the module degrades to \"no build-output fallback\" —\n * the remote cache still serves everything that has been regenerated.\n */\n private loadBuildOutputCache(): Promise<FileSystemCacheLike | undefined> {\n this.buildOutputCache ??= (async () => {\n if (!this.context.fs || !this.context.serverDistDir) return undefined;\n try {\n const module: unknown = await import('next/dist/server/lib/incremental-cache/file-system-cache.js');\n // Next ships this as CommonJS, so the constructor sits behind a different\n // number of `default` hops depending on whether this bundle was loaded as\n // CJS or ESM. Unwrap until a callable turns up rather than guessing.\n let candidate: unknown = module;\n for (let hop = 0; hop < 3 && candidate && typeof candidate !== 'function'; hop += 1) {\n candidate = (candidate as { default?: unknown }).default;\n }\n if (typeof candidate !== 'function') return undefined;\n const FileSystemCache = candidate as new (context: CacheHandlerConstructorContext) => FileSystemCacheLike;\n return new FileSystemCache(this.context);\n } catch {\n return undefined;\n }\n })();\n return this.buildOutputCache;\n }\n\n /**\n * Applies remote tag state to an entry.\n *\n * @returns the entry, a stale-marked copy, or `null` when a tag expired.\n */\n private async applyTagState(entry: IncrementalCacheEntry, tags: string[]): Promise<IncrementalCacheEntry | null> {\n if (tags.length === 0) return entry;\n const tagState = await getRuntimeCacheTagState('incremental', tags);\n if (tagState.expired > entry.lastModified) return null;\n return tagState.stale > entry.lastModified ? { ...entry, lastModified: 1 } : entry;\n }\n\n async get(key: string, context: IncrementalCacheContext = {}): Promise<IncrementalCacheEntry | null> {\n if (isBuildPhase()) {\n const buildEntry = this.buildEntries.get(key) ?? null;\n return isIncrementalCacheEntry(buildEntry) ? buildEntry : null;\n }\n\n const local = localEntries.get(key);\n if (local) {\n return this.applyTagState(local, collectTags(local.tags, local.value, context));\n }\n\n const remote = await readRuntimeCache('incremental', key);\n if (isIncrementalCacheEntry(remote)) {\n localEntries.set(key, remote);\n return this.applyTagState(remote, collectTags(remote.tags, remote.value, context));\n }\n\n // Nothing regenerated yet: fall back to the build-time prerender shipped in\n // the bundle. Tag expiry is still resolved against the remote index — Next's\n // reader only knows its own in-process tag manifest, which is always empty\n // here, so trusting it would resurrect content after a `revalidateTag`.\n const buildOutputCache = await this.loadBuildOutputCache();\n const fromDisk = await buildOutputCache?.get(key, context).catch(() => null);\n if (!isIncrementalCacheEntry(fromDisk)) return null;\n return this.applyTagState(fromDisk, collectTags(fromDisk.tags, fromDisk.value, context));\n }\n\n async set(key: string, data: unknown, context: IncrementalCacheContext): Promise<void> {\n const tags = collectTags(undefined, data, context);\n const entry = { lastModified: Date.now(), value: data, tags, cacheControl: context.cacheControl };\n if (isBuildPhase()) {\n this.buildEntries.set(key, entry);\n return;\n }\n localEntries.set(key, entry);\n try {\n await writeRuntimeCache('incremental', key, entry, tags);\n } catch (error) {\n // The local copy would outlive a failed durable write and mask it from\n // this instance for the whole TTL; drop it so reads retry remotely.\n localEntries.delete(key);\n throw error;\n }\n }\n\n async revalidateTag(tags: string | string[], durations?: { expire?: number }): Promise<void> {\n const normalizedTags = Array.isArray(tags) ? tags : [tags];\n if (isBuildPhase()) {\n for (const [key, entry] of this.buildEntries) {\n if (entry.tags?.some((tag) => normalizedTags.includes(tag))) this.buildEntries.delete(key);\n }\n return;\n }\n await revalidateRuntimeCacheTags('incremental', normalizedTags, durations);\n }\n\n resetRequestCache(): void {}\n}\n","interface RuntimeCacheEnvelope {\n value: unknown;\n}\n\ninterface AccessTokenResponse {\n access_token: string;\n expires_in?: number;\n}\n\nexport interface RuntimeCacheTagState {\n stale: number;\n expired: number;\n}\n\nlet cachedToken: { value: string; expiresAt: number } | undefined;\n\nconst apiBaseUrl = (): string => (process.env.GIGADRIVE_API_URL ?? 'https://api.gigadrive.network').replace(/\\/$/, '');\n\nconst encodeBinary = (value: unknown, seen = new WeakSet<object>()): unknown => {\n if (value instanceof Uint8Array) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n if (value instanceof ArrayBuffer) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n // Next stores App Router RSC segment payloads as a `Map<string, Buffer>`\n // (`segmentData`). `Object.entries` on a Map yields nothing, so without an\n // explicit branch the whole map would serialize to `{}` and every prefetched\n // segment would be silently lost on the next read.\n if (value instanceof Map) {\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const entries = [...value.entries()].map(([key, item]) => [encodeBinary(key, seen), encodeBinary(item, seen)]);\n seen.delete(value);\n return { __gigadriveType: 'map', value: entries };\n }\n if (Array.isArray(value)) return value.map((item) => encodeBinary(item, seen));\n if (typeof value !== 'object' || value === null) return value;\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) result[key] = encodeBinary(item, seen);\n seen.delete(value);\n return result;\n};\n\nconst decodeBinary = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(decodeBinary);\n if (typeof value !== 'object' || value === null) return value;\n const record = value as Record<string, unknown>;\n if (record.__gigadriveType === 'bytes' && typeof record.value === 'string')\n return Buffer.from(record.value, 'base64');\n if (record.__gigadriveType === 'map' && Array.isArray(record.value)) {\n return new Map(\n (record.value as unknown[]).map((entry) => {\n const [key, item] = entry as [unknown, unknown];\n return [decodeBinary(key), decodeBinary(item)];\n })\n );\n }\n return Object.fromEntries(Object.entries(record).map(([key, item]) => [key, decodeBinary(item)]));\n};\n\nconst getAccessToken = async (): Promise<string> => {\n if (cachedToken && cachedToken.expiresAt > Date.now() + 30_000) return cachedToken.value;\n const clientId = process.env.GIGADRIVE_CLIENT_ID;\n const clientSecret = process.env.GIGADRIVE_CLIENT_SECRET;\n if (!clientId || !clientSecret) throw new Error('Gigadrive workload credentials are unavailable');\n\n const response = await fetch(`${apiBaseUrl()}/oauth2/token`, {\n method: 'POST',\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,\n 'content-type': 'application/x-www-form-urlencoded',\n },\n body: 'grant_type=client_credentials',\n });\n if (!response.ok) throw new Error(`Gigadrive workload authentication failed with status ${response.status}`);\n const token = (await response.json()) as AccessTokenResponse;\n if (!token.access_token) throw new Error('Gigadrive workload authentication returned no access token');\n cachedToken = {\n value: token.access_token,\n expiresAt: Date.now() + Math.max(60, token.expires_in ?? 300) * 1000,\n };\n return token.access_token;\n};\n\nconst request = async (pathname: string, init: RequestInit, attempt = 0): Promise<Response> => {\n const token = await getAccessToken();\n try {\n const response = await fetch(`${apiBaseUrl()}${pathname}`, {\n ...init,\n headers: {\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n 'x-gigadrive-deployment-id': process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? '',\n 'x-gigadrive-build-id': process.env.NEXT_BUILD_ID ?? '',\n ...init.headers,\n },\n });\n if (response.status === 401 && attempt === 0) {\n cachedToken = undefined;\n return request(pathname, init, attempt + 1);\n }\n if (response.status >= 500 && attempt < 2) return request(pathname, init, attempt + 1);\n return response;\n } catch (error) {\n if (attempt < 2) return request(pathname, init, attempt + 1);\n throw error;\n }\n};\n\nconst cachePath = (kind: string, key: string): string =>\n `/internal/runtime-cache/v1/entries/${encodeURIComponent(kind)}/${encodeURIComponent(key)}`;\n\nexport const readRuntimeCache = async (kind: string, key: string): Promise<unknown | undefined> => {\n try {\n const response = await request(cachePath(kind, key), { method: 'GET' });\n if (response.status === 404) return undefined;\n if (!response.ok) return undefined;\n const envelope = (await response.json()) as RuntimeCacheEnvelope;\n return decodeBinary(envelope.value);\n } catch {\n return undefined;\n }\n};\n\nexport const writeRuntimeCache = async (\n kind: string,\n key: string,\n value: unknown,\n tags: readonly string[] = []\n): Promise<void> => {\n const response = await request(cachePath(kind, key), {\n method: 'PUT',\n body: JSON.stringify({ value: encodeBinary(value), tags }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache write failed with status ${response.status}`);\n};\n\nexport const revalidateRuntimeCacheTags = async (\n kind: string,\n tags: readonly string[],\n durations?: { expire?: number }\n): Promise<void> => {\n const response = await request('/internal/runtime-cache/v1/tags/revalidate', {\n method: 'POST',\n body: JSON.stringify({ kind, tags, durations }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache revalidation failed with status ${response.status}`);\n};\n\nexport const getRuntimeCacheTagExpiration = async (kind: string, tags: readonly string[]): Promise<number> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/expiration', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return 0;\n const value = (await response.json()) as { expiration?: unknown };\n return typeof value.expiration === 'number' ? value.expiration : 0;\n } catch {\n return 0;\n }\n};\n\nexport const getRuntimeCacheTagState = async (kind: string, tags: readonly string[]): Promise<RuntimeCacheTagState> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/state', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return { stale: 0, expired: 0 };\n const value = (await response.json()) as { stale?: unknown; expired?: unknown };\n return {\n stale: typeof value.stale === 'number' ? value.stale : 0,\n expired: typeof value.expired === 'number' ? value.expired : 0,\n };\n } catch {\n return { stale: 0, expired: 0 };\n }\n};\n\nexport const resetRuntimeCacheClientForTests = (): void => {\n cachedToken = undefined;\n};\n\n/**\n * Re-establishes the client's network state after a microVM resume.\n *\n * The guest runtime delivers SIGUSR2 when the instance is restored from a\n * suspend snapshot. At that moment every kept-alive TCP connection from before\n * the freeze is dead, and the cached OAuth token may have expired while the\n * clock was stopped. Dropping the token and dialing one throwaway read\n * re-opens TCP+TLS and refreshes the token concurrently with the guest's own\n * wake-up work, so the first real cache read after a resume does not\n * serialize behind reconnection.\n *\n * Registered only when a Gigadrive deployment marker is present in the\n * environment, so local `next dev`/`next build` never gains a signal listener.\n */\nconst registerResumeRewarm = (): void => {\n // Next exposes this marker before evaluating an Edge route bundle. Bail out\n // before touching `process`: its Edge compatibility proxy throws when the\n // Node-only signal API is read, including through Reflect.\n if (Reflect.has(globalThis, 'EdgeRuntime')) return;\n\n // The deployment id is intentionally available during `next build`, but the\n // shared cache client is also bundled into Edge routes at that point. Keep\n // every Node-only signal reference behind the build-phase guard so Turbopack\n // can eliminate this branch before its Edge runtime validation runs.\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') return;\n\n const onGigadrive =\n process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;\n if (!onGigadrive) return;\n\n // Resolve the optional Node signal API reflectively so non-Node runtimes can\n // load the shared client while Node deployments retain resume rewarming.\n const runtimeProcess = Reflect.get(globalThis, 'process') as NodeJS.Process | undefined;\n const addSignalListener = runtimeProcess && Reflect.get(runtimeProcess, 'on');\n if (typeof addSignalListener !== 'function') return;\n\n Reflect.apply(addSignalListener, runtimeProcess, [\n 'SIGUSR2',\n () => {\n cachedToken = undefined;\n if (!process.env.GIGADRIVE_CLIENT_ID || !process.env.GIGADRIVE_CLIENT_SECRET) return;\n void readRuntimeCache('warmup', '__resume__');\n },\n ]);\n};\nregisterResumeRewarm();\n"],"mappings":"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","names":["module"]}
|
|
@@ -129,6 +129,7 @@ var getRuntimeCacheTagState = async (kind, tags) => {
|
|
|
129
129
|
}
|
|
130
130
|
};
|
|
131
131
|
var registerResumeRewarm = () => {
|
|
132
|
+
if (Reflect.has(globalThis, "EdgeRuntime")) return;
|
|
132
133
|
if (process.env.GIGADRIVE_NEXT_BUILD === "1") return;
|
|
133
134
|
const onGigadrive = process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;
|
|
134
135
|
if (!onGigadrive) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nextjs-runtime-cache-client.ts","../src/nextjs-cache-handler.ts"],"sourcesContent":["interface RuntimeCacheEnvelope {\n value: unknown;\n}\n\ninterface AccessTokenResponse {\n access_token: string;\n expires_in?: number;\n}\n\nexport interface RuntimeCacheTagState {\n stale: number;\n expired: number;\n}\n\nlet cachedToken: { value: string; expiresAt: number } | undefined;\n\nconst apiBaseUrl = (): string => (process.env.GIGADRIVE_API_URL ?? 'https://api.gigadrive.network').replace(/\\/$/, '');\n\nconst encodeBinary = (value: unknown, seen = new WeakSet<object>()): unknown => {\n if (value instanceof Uint8Array) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n if (value instanceof ArrayBuffer) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n // Next stores App Router RSC segment payloads as a `Map<string, Buffer>`\n // (`segmentData`). `Object.entries` on a Map yields nothing, so without an\n // explicit branch the whole map would serialize to `{}` and every prefetched\n // segment would be silently lost on the next read.\n if (value instanceof Map) {\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const entries = [...value.entries()].map(([key, item]) => [encodeBinary(key, seen), encodeBinary(item, seen)]);\n seen.delete(value);\n return { __gigadriveType: 'map', value: entries };\n }\n if (Array.isArray(value)) return value.map((item) => encodeBinary(item, seen));\n if (typeof value !== 'object' || value === null) return value;\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) result[key] = encodeBinary(item, seen);\n seen.delete(value);\n return result;\n};\n\nconst decodeBinary = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(decodeBinary);\n if (typeof value !== 'object' || value === null) return value;\n const record = value as Record<string, unknown>;\n if (record.__gigadriveType === 'bytes' && typeof record.value === 'string')\n return Buffer.from(record.value, 'base64');\n if (record.__gigadriveType === 'map' && Array.isArray(record.value)) {\n return new Map(\n (record.value as unknown[]).map((entry) => {\n const [key, item] = entry as [unknown, unknown];\n return [decodeBinary(key), decodeBinary(item)];\n })\n );\n }\n return Object.fromEntries(Object.entries(record).map(([key, item]) => [key, decodeBinary(item)]));\n};\n\nconst getAccessToken = async (): Promise<string> => {\n if (cachedToken && cachedToken.expiresAt > Date.now() + 30_000) return cachedToken.value;\n const clientId = process.env.GIGADRIVE_CLIENT_ID;\n const clientSecret = process.env.GIGADRIVE_CLIENT_SECRET;\n if (!clientId || !clientSecret) throw new Error('Gigadrive workload credentials are unavailable');\n\n const response = await fetch(`${apiBaseUrl()}/oauth2/token`, {\n method: 'POST',\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,\n 'content-type': 'application/x-www-form-urlencoded',\n },\n body: 'grant_type=client_credentials',\n });\n if (!response.ok) throw new Error(`Gigadrive workload authentication failed with status ${response.status}`);\n const token = (await response.json()) as AccessTokenResponse;\n if (!token.access_token) throw new Error('Gigadrive workload authentication returned no access token');\n cachedToken = {\n value: token.access_token,\n expiresAt: Date.now() + Math.max(60, token.expires_in ?? 300) * 1000,\n };\n return token.access_token;\n};\n\nconst request = async (pathname: string, init: RequestInit, attempt = 0): Promise<Response> => {\n const token = await getAccessToken();\n try {\n const response = await fetch(`${apiBaseUrl()}${pathname}`, {\n ...init,\n headers: {\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n 'x-gigadrive-deployment-id': process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? '',\n 'x-gigadrive-build-id': process.env.NEXT_BUILD_ID ?? '',\n ...init.headers,\n },\n });\n if (response.status === 401 && attempt === 0) {\n cachedToken = undefined;\n return request(pathname, init, attempt + 1);\n }\n if (response.status >= 500 && attempt < 2) return request(pathname, init, attempt + 1);\n return response;\n } catch (error) {\n if (attempt < 2) return request(pathname, init, attempt + 1);\n throw error;\n }\n};\n\nconst cachePath = (kind: string, key: string): string =>\n `/internal/runtime-cache/v1/entries/${encodeURIComponent(kind)}/${encodeURIComponent(key)}`;\n\nexport const readRuntimeCache = async (kind: string, key: string): Promise<unknown | undefined> => {\n try {\n const response = await request(cachePath(kind, key), { method: 'GET' });\n if (response.status === 404) return undefined;\n if (!response.ok) return undefined;\n const envelope = (await response.json()) as RuntimeCacheEnvelope;\n return decodeBinary(envelope.value);\n } catch {\n return undefined;\n }\n};\n\nexport const writeRuntimeCache = async (\n kind: string,\n key: string,\n value: unknown,\n tags: readonly string[] = []\n): Promise<void> => {\n const response = await request(cachePath(kind, key), {\n method: 'PUT',\n body: JSON.stringify({ value: encodeBinary(value), tags }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache write failed with status ${response.status}`);\n};\n\nexport const revalidateRuntimeCacheTags = async (\n kind: string,\n tags: readonly string[],\n durations?: { expire?: number }\n): Promise<void> => {\n const response = await request('/internal/runtime-cache/v1/tags/revalidate', {\n method: 'POST',\n body: JSON.stringify({ kind, tags, durations }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache revalidation failed with status ${response.status}`);\n};\n\nexport const getRuntimeCacheTagExpiration = async (kind: string, tags: readonly string[]): Promise<number> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/expiration', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return 0;\n const value = (await response.json()) as { expiration?: unknown };\n return typeof value.expiration === 'number' ? value.expiration : 0;\n } catch {\n return 0;\n }\n};\n\nexport const getRuntimeCacheTagState = async (kind: string, tags: readonly string[]): Promise<RuntimeCacheTagState> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/state', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return { stale: 0, expired: 0 };\n const value = (await response.json()) as { stale?: unknown; expired?: unknown };\n return {\n stale: typeof value.stale === 'number' ? value.stale : 0,\n expired: typeof value.expired === 'number' ? value.expired : 0,\n };\n } catch {\n return { stale: 0, expired: 0 };\n }\n};\n\nexport const resetRuntimeCacheClientForTests = (): void => {\n cachedToken = undefined;\n};\n\n/**\n * Re-establishes the client's network state after a microVM resume.\n *\n * The guest runtime delivers SIGUSR2 when the instance is restored from a\n * suspend snapshot. At that moment every kept-alive TCP connection from before\n * the freeze is dead, and the cached OAuth token may have expired while the\n * clock was stopped. Dropping the token and dialing one throwaway read\n * re-opens TCP+TLS and refreshes the token concurrently with the guest's own\n * wake-up work, so the first real cache read after a resume does not\n * serialize behind reconnection.\n *\n * Registered only when a Gigadrive deployment marker is present in the\n * environment, so local `next dev`/`next build` never gains a signal listener.\n */\nconst registerResumeRewarm = (): void => {\n // The deployment id is intentionally available during `next build`, but the\n // shared cache client is also bundled into Edge routes at that point. Keep\n // every Node-only signal reference behind the build-phase guard so Turbopack\n // can eliminate this branch before its Edge runtime validation runs.\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') return;\n\n const onGigadrive =\n process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;\n if (!onGigadrive) return;\n\n // This module is shared by Node and Edge cache-handler bundles. Next.js 16.2\n // rejects a statically analyzable `process.on` call while collecting Edge\n // route data, even though the listener only runs inside the Node runtime.\n // Resolve the optional Node signal API reflectively so Edge builds can load\n // the shared client while Node deployments retain resume rewarming.\n const runtimeProcess = Reflect.get(globalThis, 'process') as NodeJS.Process | undefined;\n const addSignalListener = runtimeProcess && Reflect.get(runtimeProcess, 'on');\n if (typeof addSignalListener !== 'function') return;\n\n Reflect.apply(addSignalListener, runtimeProcess, [\n 'SIGUSR2',\n () => {\n cachedToken = undefined;\n if (!process.env.GIGADRIVE_CLIENT_ID || !process.env.GIGADRIVE_CLIENT_SECRET) return;\n void readRuntimeCache('warmup', '__resume__');\n },\n ]);\n};\nregisterResumeRewarm();\n","import {\n getRuntimeCacheTagState,\n readRuntimeCache,\n revalidateRuntimeCacheTags,\n writeRuntimeCache,\n} from './nextjs-runtime-cache-client';\n\n/** Header Next uses to carry an entry's cache tags (comma separated). */\nconst NEXT_CACHE_TAGS_HEADER = 'x-next-cache-tags';\n\ninterface IncrementalCacheContext {\n tags?: string[];\n softTags?: string[];\n cacheControl?: unknown;\n kind?: string;\n}\n\ninterface IncrementalCacheEntry {\n lastModified: number;\n value: unknown | null;\n tags?: string[];\n cacheControl?: unknown;\n}\n\n/** Constructor context Next passes to a custom cache handler. */\ninterface CacheHandlerConstructorContext {\n fs?: unknown;\n serverDistDir?: string;\n dev?: boolean;\n flushToDisk?: boolean;\n revalidatedTags?: string[];\n maxMemoryCacheSize?: number;\n _requestHeaders?: unknown;\n fetchCacheKeyPrefix?: string;\n}\n\ninterface FileSystemCacheLike {\n get(key: string, context: IncrementalCacheContext): Promise<IncrementalCacheEntry | null | undefined>;\n}\n\nconst isIncrementalCacheEntry = (value: unknown): value is IncrementalCacheEntry =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<IncrementalCacheEntry>).lastModified === 'number' &&\n 'value' in value;\n\n/**\n * Reads the cache tags carried by a cached value's own headers.\n *\n * Next never populates `context.tags` for APP_PAGE/APP_ROUTE/PAGES — only fetch\n * cache entries carry tags on the context. For route entries the tags live in\n * the cached value's headers under `x-next-cache-tags` as a comma-joined string,\n * so reading them here is what keeps the remote tag index (and therefore\n * `revalidateTag`) working for pages and route handlers.\n */\nconst valueTags = (value: unknown): string[] => {\n const header = (value as { headers?: Record<string, unknown> } | null)?.headers?.[NEXT_CACHE_TAGS_HEADER];\n if (typeof header !== 'string') return [];\n return header\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean);\n};\n\n/** Every tag relevant to an entry: its own, the request's, and the value's headers. */\nconst collectTags = (\n entryTags: string[] | undefined,\n value: unknown,\n context: IncrementalCacheContext = {}\n): string[] => [\n ...new Set([...(entryTags ?? []), ...(context.tags ?? []), ...(context.softTags ?? []), ...valueTags(value)]),\n];\n\nconst isBuildPhase = (): boolean => process.env.GIGADRIVE_NEXT_BUILD === '1';\n\n/**\n * How long a locally cached entry may serve before the remote copy is re-read.\n * Bounds staleness when another instance rewrites the entry; tag-driven\n * invalidation is unaffected because tag state is checked remotely on every\n * read regardless of where the entry bytes came from.\n */\nconst LOCAL_ENTRY_TTL_MS = 5 * 60_000;\nconst LOCAL_CACHE_MAX_ENTRIES = 256;\nconst LOCAL_CACHE_MAX_TOTAL_BYTES = 64 * 1024 * 1024;\nconst LOCAL_CACHE_MAX_ENTRY_BYTES = 8 * 1024 * 1024;\n\ninterface LocalCacheSlot {\n entry: IncrementalCacheEntry;\n cachedAt: number;\n bytes: number;\n}\n\nconst approximateEntryBytes = (entry: IncrementalCacheEntry): number => {\n try {\n return JSON.stringify(entry)?.length ?? LOCAL_CACHE_MAX_ENTRY_BYTES + 1;\n } catch {\n // Circular or otherwise unserializable values are never cached locally.\n return LOCAL_CACHE_MAX_ENTRY_BYTES + 1;\n }\n};\n\n/**\n * Byte-bounded in-process LRU in front of the remote entry store.\n *\n * The remote store is an HTTP service backed by object storage, so every miss\n * costs a network round trip — and when that store degrades, page renders\n * degrade with it (a production incident showed second-level blob latency\n * turning every render of a cached page into a multi-second response).\n * Serving entry bytes locally removes that dependency from the hot path while\n * the per-read remote tag-state check keeps `revalidateTag` authoritative.\n */\nclass LocalEntryCache {\n private readonly slots = new Map<string, LocalCacheSlot>();\n private totalBytes = 0;\n\n get(key: string): IncrementalCacheEntry | undefined {\n const slot = this.slots.get(key);\n if (!slot) return undefined;\n if (Date.now() - slot.cachedAt > LOCAL_ENTRY_TTL_MS) {\n this.delete(key);\n return undefined;\n }\n // Refresh recency for LRU eviction.\n this.slots.delete(key);\n this.slots.set(key, slot);\n return slot.entry;\n }\n\n set(key: string, entry: IncrementalCacheEntry): void {\n const bytes = approximateEntryBytes(entry);\n if (bytes > LOCAL_CACHE_MAX_ENTRY_BYTES) {\n this.delete(key);\n return;\n }\n this.delete(key);\n this.slots.set(key, { entry, cachedAt: Date.now(), bytes });\n this.totalBytes += bytes;\n while (this.slots.size > LOCAL_CACHE_MAX_ENTRIES || this.totalBytes > LOCAL_CACHE_MAX_TOTAL_BYTES) {\n const oldest = this.slots.keys().next().value;\n if (oldest === undefined) break;\n this.delete(oldest);\n }\n }\n\n delete(key: string): void {\n const slot = this.slots.get(key);\n if (!slot) return;\n this.slots.delete(key);\n this.totalBytes -= slot.bytes;\n }\n\n clear(): void {\n this.slots.clear();\n this.totalBytes = 0;\n }\n}\n\nconst localEntries = new LocalEntryCache();\n\n/** Test-only: the local entry cache is process-wide, so suites must isolate it. */\nexport const clearLocalEntryCacheForTesting = (): void => localEntries.clear();\n\n/** Shared Network cache handler for ISR, server responses, fetches, and image metadata. */\nexport default class GigadriveNextCacheHandler {\n private readonly buildEntries = new Map<string, IncrementalCacheEntry>();\n /**\n * Next's own on-disk reader, pointed at the build output that ships inside the\n * deployment bundle (`writeStandaloneDirectory` recursively copies\n * `.next/server/{app,pages}`). Injecting a `cacheHandler` replaces Next's\n * FileSystemCache outright, which would otherwise strand every build-time\n * prerender and force a cold re-render of each page on first request.\n * Delegating to Next's reader keeps us off its private on-disk format.\n */\n private buildOutputCache?: Promise<FileSystemCacheLike | undefined>;\n private readonly context: CacheHandlerConstructorContext;\n\n constructor(context: CacheHandlerConstructorContext = {}) {\n this.context = context;\n }\n\n /**\n * Loads Next's on-disk reader lazily, memoized across requests. A Next release\n * that moves or renames the module degrades to \"no build-output fallback\" —\n * the remote cache still serves everything that has been regenerated.\n */\n private loadBuildOutputCache(): Promise<FileSystemCacheLike | undefined> {\n this.buildOutputCache ??= (async () => {\n if (!this.context.fs || !this.context.serverDistDir) return undefined;\n try {\n const module: unknown = await import('next/dist/server/lib/incremental-cache/file-system-cache.js');\n // Next ships this as CommonJS, so the constructor sits behind a different\n // number of `default` hops depending on whether this bundle was loaded as\n // CJS or ESM. Unwrap until a callable turns up rather than guessing.\n let candidate: unknown = module;\n for (let hop = 0; hop < 3 && candidate && typeof candidate !== 'function'; hop += 1) {\n candidate = (candidate as { default?: unknown }).default;\n }\n if (typeof candidate !== 'function') return undefined;\n const FileSystemCache = candidate as new (context: CacheHandlerConstructorContext) => FileSystemCacheLike;\n return new FileSystemCache(this.context);\n } catch {\n return undefined;\n }\n })();\n return this.buildOutputCache;\n }\n\n /**\n * Applies remote tag state to an entry.\n *\n * @returns the entry, a stale-marked copy, or `null` when a tag expired.\n */\n private async applyTagState(entry: IncrementalCacheEntry, tags: string[]): Promise<IncrementalCacheEntry | null> {\n if (tags.length === 0) return entry;\n const tagState = await getRuntimeCacheTagState('incremental', tags);\n if (tagState.expired > entry.lastModified) return null;\n return tagState.stale > entry.lastModified ? { ...entry, lastModified: 1 } : entry;\n }\n\n async get(key: string, context: IncrementalCacheContext = {}): Promise<IncrementalCacheEntry | null> {\n if (isBuildPhase()) {\n const buildEntry = this.buildEntries.get(key) ?? null;\n return isIncrementalCacheEntry(buildEntry) ? buildEntry : null;\n }\n\n const local = localEntries.get(key);\n if (local) {\n return this.applyTagState(local, collectTags(local.tags, local.value, context));\n }\n\n const remote = await readRuntimeCache('incremental', key);\n if (isIncrementalCacheEntry(remote)) {\n localEntries.set(key, remote);\n return this.applyTagState(remote, collectTags(remote.tags, remote.value, context));\n }\n\n // Nothing regenerated yet: fall back to the build-time prerender shipped in\n // the bundle. Tag expiry is still resolved against the remote index — Next's\n // reader only knows its own in-process tag manifest, which is always empty\n // here, so trusting it would resurrect content after a `revalidateTag`.\n const buildOutputCache = await this.loadBuildOutputCache();\n const fromDisk = await buildOutputCache?.get(key, context).catch(() => null);\n if (!isIncrementalCacheEntry(fromDisk)) return null;\n return this.applyTagState(fromDisk, collectTags(fromDisk.tags, fromDisk.value, context));\n }\n\n async set(key: string, data: unknown, context: IncrementalCacheContext): Promise<void> {\n const tags = collectTags(undefined, data, context);\n const entry = { lastModified: Date.now(), value: data, tags, cacheControl: context.cacheControl };\n if (isBuildPhase()) {\n this.buildEntries.set(key, entry);\n return;\n }\n localEntries.set(key, entry);\n try {\n await writeRuntimeCache('incremental', key, entry, tags);\n } catch (error) {\n // The local copy would outlive a failed durable write and mask it from\n // this instance for the whole TTL; drop it so reads retry remotely.\n localEntries.delete(key);\n throw error;\n }\n }\n\n async revalidateTag(tags: string | string[], durations?: { expire?: number }): Promise<void> {\n const normalizedTags = Array.isArray(tags) ? tags : [tags];\n if (isBuildPhase()) {\n for (const [key, entry] of this.buildEntries) {\n if (entry.tags?.some((tag) => normalizedTags.includes(tag))) this.buildEntries.delete(key);\n }\n return;\n }\n await revalidateRuntimeCacheTags('incremental', normalizedTags, durations);\n }\n\n resetRequestCache(): void {}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/nextjs-runtime-cache-client.ts","../src/nextjs-cache-handler.ts"],"sourcesContent":["interface RuntimeCacheEnvelope {\n value: unknown;\n}\n\ninterface AccessTokenResponse {\n access_token: string;\n expires_in?: number;\n}\n\nexport interface RuntimeCacheTagState {\n stale: number;\n expired: number;\n}\n\nlet cachedToken: { value: string; expiresAt: number } | undefined;\n\nconst apiBaseUrl = (): string => (process.env.GIGADRIVE_API_URL ?? 'https://api.gigadrive.network').replace(/\\/$/, '');\n\nconst encodeBinary = (value: unknown, seen = new WeakSet<object>()): unknown => {\n if (value instanceof Uint8Array) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n if (value instanceof ArrayBuffer) {\n return { __gigadriveType: 'bytes', value: Buffer.from(value).toString('base64') };\n }\n // Next stores App Router RSC segment payloads as a `Map<string, Buffer>`\n // (`segmentData`). `Object.entries` on a Map yields nothing, so without an\n // explicit branch the whole map would serialize to `{}` and every prefetched\n // segment would be silently lost on the next read.\n if (value instanceof Map) {\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const entries = [...value.entries()].map(([key, item]) => [encodeBinary(key, seen), encodeBinary(item, seen)]);\n seen.delete(value);\n return { __gigadriveType: 'map', value: entries };\n }\n if (Array.isArray(value)) return value.map((item) => encodeBinary(item, seen));\n if (typeof value !== 'object' || value === null) return value;\n if (seen.has(value)) throw new Error('Next.js cache entry contains a circular value');\n seen.add(value);\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) result[key] = encodeBinary(item, seen);\n seen.delete(value);\n return result;\n};\n\nconst decodeBinary = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(decodeBinary);\n if (typeof value !== 'object' || value === null) return value;\n const record = value as Record<string, unknown>;\n if (record.__gigadriveType === 'bytes' && typeof record.value === 'string')\n return Buffer.from(record.value, 'base64');\n if (record.__gigadriveType === 'map' && Array.isArray(record.value)) {\n return new Map(\n (record.value as unknown[]).map((entry) => {\n const [key, item] = entry as [unknown, unknown];\n return [decodeBinary(key), decodeBinary(item)];\n })\n );\n }\n return Object.fromEntries(Object.entries(record).map(([key, item]) => [key, decodeBinary(item)]));\n};\n\nconst getAccessToken = async (): Promise<string> => {\n if (cachedToken && cachedToken.expiresAt > Date.now() + 30_000) return cachedToken.value;\n const clientId = process.env.GIGADRIVE_CLIENT_ID;\n const clientSecret = process.env.GIGADRIVE_CLIENT_SECRET;\n if (!clientId || !clientSecret) throw new Error('Gigadrive workload credentials are unavailable');\n\n const response = await fetch(`${apiBaseUrl()}/oauth2/token`, {\n method: 'POST',\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,\n 'content-type': 'application/x-www-form-urlencoded',\n },\n body: 'grant_type=client_credentials',\n });\n if (!response.ok) throw new Error(`Gigadrive workload authentication failed with status ${response.status}`);\n const token = (await response.json()) as AccessTokenResponse;\n if (!token.access_token) throw new Error('Gigadrive workload authentication returned no access token');\n cachedToken = {\n value: token.access_token,\n expiresAt: Date.now() + Math.max(60, token.expires_in ?? 300) * 1000,\n };\n return token.access_token;\n};\n\nconst request = async (pathname: string, init: RequestInit, attempt = 0): Promise<Response> => {\n const token = await getAccessToken();\n try {\n const response = await fetch(`${apiBaseUrl()}${pathname}`, {\n ...init,\n headers: {\n authorization: `Bearer ${token}`,\n 'content-type': 'application/json',\n 'x-gigadrive-deployment-id': process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? '',\n 'x-gigadrive-build-id': process.env.NEXT_BUILD_ID ?? '',\n ...init.headers,\n },\n });\n if (response.status === 401 && attempt === 0) {\n cachedToken = undefined;\n return request(pathname, init, attempt + 1);\n }\n if (response.status >= 500 && attempt < 2) return request(pathname, init, attempt + 1);\n return response;\n } catch (error) {\n if (attempt < 2) return request(pathname, init, attempt + 1);\n throw error;\n }\n};\n\nconst cachePath = (kind: string, key: string): string =>\n `/internal/runtime-cache/v1/entries/${encodeURIComponent(kind)}/${encodeURIComponent(key)}`;\n\nexport const readRuntimeCache = async (kind: string, key: string): Promise<unknown | undefined> => {\n try {\n const response = await request(cachePath(kind, key), { method: 'GET' });\n if (response.status === 404) return undefined;\n if (!response.ok) return undefined;\n const envelope = (await response.json()) as RuntimeCacheEnvelope;\n return decodeBinary(envelope.value);\n } catch {\n return undefined;\n }\n};\n\nexport const writeRuntimeCache = async (\n kind: string,\n key: string,\n value: unknown,\n tags: readonly string[] = []\n): Promise<void> => {\n const response = await request(cachePath(kind, key), {\n method: 'PUT',\n body: JSON.stringify({ value: encodeBinary(value), tags }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache write failed with status ${response.status}`);\n};\n\nexport const revalidateRuntimeCacheTags = async (\n kind: string,\n tags: readonly string[],\n durations?: { expire?: number }\n): Promise<void> => {\n const response = await request('/internal/runtime-cache/v1/tags/revalidate', {\n method: 'POST',\n body: JSON.stringify({ kind, tags, durations }),\n });\n if (!response.ok) throw new Error(`Gigadrive runtime cache revalidation failed with status ${response.status}`);\n};\n\nexport const getRuntimeCacheTagExpiration = async (kind: string, tags: readonly string[]): Promise<number> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/expiration', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return 0;\n const value = (await response.json()) as { expiration?: unknown };\n return typeof value.expiration === 'number' ? value.expiration : 0;\n } catch {\n return 0;\n }\n};\n\nexport const getRuntimeCacheTagState = async (kind: string, tags: readonly string[]): Promise<RuntimeCacheTagState> => {\n try {\n const response = await request('/internal/runtime-cache/v1/tags/state', {\n method: 'POST',\n body: JSON.stringify({ kind, tags }),\n });\n if (!response.ok) return { stale: 0, expired: 0 };\n const value = (await response.json()) as { stale?: unknown; expired?: unknown };\n return {\n stale: typeof value.stale === 'number' ? value.stale : 0,\n expired: typeof value.expired === 'number' ? value.expired : 0,\n };\n } catch {\n return { stale: 0, expired: 0 };\n }\n};\n\nexport const resetRuntimeCacheClientForTests = (): void => {\n cachedToken = undefined;\n};\n\n/**\n * Re-establishes the client's network state after a microVM resume.\n *\n * The guest runtime delivers SIGUSR2 when the instance is restored from a\n * suspend snapshot. At that moment every kept-alive TCP connection from before\n * the freeze is dead, and the cached OAuth token may have expired while the\n * clock was stopped. Dropping the token and dialing one throwaway read\n * re-opens TCP+TLS and refreshes the token concurrently with the guest's own\n * wake-up work, so the first real cache read after a resume does not\n * serialize behind reconnection.\n *\n * Registered only when a Gigadrive deployment marker is present in the\n * environment, so local `next dev`/`next build` never gains a signal listener.\n */\nconst registerResumeRewarm = (): void => {\n // Next exposes this marker before evaluating an Edge route bundle. Bail out\n // before touching `process`: its Edge compatibility proxy throws when the\n // Node-only signal API is read, including through Reflect.\n if (Reflect.has(globalThis, 'EdgeRuntime')) return;\n\n // The deployment id is intentionally available during `next build`, but the\n // shared cache client is also bundled into Edge routes at that point. Keep\n // every Node-only signal reference behind the build-phase guard so Turbopack\n // can eliminate this branch before its Edge runtime validation runs.\n if (process.env.GIGADRIVE_NEXT_BUILD === '1') return;\n\n const onGigadrive =\n process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? process.env.GIGADRIVE_CLIENT_ID;\n if (!onGigadrive) return;\n\n // Resolve the optional Node signal API reflectively so non-Node runtimes can\n // load the shared client while Node deployments retain resume rewarming.\n const runtimeProcess = Reflect.get(globalThis, 'process') as NodeJS.Process | undefined;\n const addSignalListener = runtimeProcess && Reflect.get(runtimeProcess, 'on');\n if (typeof addSignalListener !== 'function') return;\n\n Reflect.apply(addSignalListener, runtimeProcess, [\n 'SIGUSR2',\n () => {\n cachedToken = undefined;\n if (!process.env.GIGADRIVE_CLIENT_ID || !process.env.GIGADRIVE_CLIENT_SECRET) return;\n void readRuntimeCache('warmup', '__resume__');\n },\n ]);\n};\nregisterResumeRewarm();\n","import {\n getRuntimeCacheTagState,\n readRuntimeCache,\n revalidateRuntimeCacheTags,\n writeRuntimeCache,\n} from './nextjs-runtime-cache-client';\n\n/** Header Next uses to carry an entry's cache tags (comma separated). */\nconst NEXT_CACHE_TAGS_HEADER = 'x-next-cache-tags';\n\ninterface IncrementalCacheContext {\n tags?: string[];\n softTags?: string[];\n cacheControl?: unknown;\n kind?: string;\n}\n\ninterface IncrementalCacheEntry {\n lastModified: number;\n value: unknown | null;\n tags?: string[];\n cacheControl?: unknown;\n}\n\n/** Constructor context Next passes to a custom cache handler. */\ninterface CacheHandlerConstructorContext {\n fs?: unknown;\n serverDistDir?: string;\n dev?: boolean;\n flushToDisk?: boolean;\n revalidatedTags?: string[];\n maxMemoryCacheSize?: number;\n _requestHeaders?: unknown;\n fetchCacheKeyPrefix?: string;\n}\n\ninterface FileSystemCacheLike {\n get(key: string, context: IncrementalCacheContext): Promise<IncrementalCacheEntry | null | undefined>;\n}\n\nconst isIncrementalCacheEntry = (value: unknown): value is IncrementalCacheEntry =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<IncrementalCacheEntry>).lastModified === 'number' &&\n 'value' in value;\n\n/**\n * Reads the cache tags carried by a cached value's own headers.\n *\n * Next never populates `context.tags` for APP_PAGE/APP_ROUTE/PAGES — only fetch\n * cache entries carry tags on the context. For route entries the tags live in\n * the cached value's headers under `x-next-cache-tags` as a comma-joined string,\n * so reading them here is what keeps the remote tag index (and therefore\n * `revalidateTag`) working for pages and route handlers.\n */\nconst valueTags = (value: unknown): string[] => {\n const header = (value as { headers?: Record<string, unknown> } | null)?.headers?.[NEXT_CACHE_TAGS_HEADER];\n if (typeof header !== 'string') return [];\n return header\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean);\n};\n\n/** Every tag relevant to an entry: its own, the request's, and the value's headers. */\nconst collectTags = (\n entryTags: string[] | undefined,\n value: unknown,\n context: IncrementalCacheContext = {}\n): string[] => [\n ...new Set([...(entryTags ?? []), ...(context.tags ?? []), ...(context.softTags ?? []), ...valueTags(value)]),\n];\n\nconst isBuildPhase = (): boolean => process.env.GIGADRIVE_NEXT_BUILD === '1';\n\n/**\n * How long a locally cached entry may serve before the remote copy is re-read.\n * Bounds staleness when another instance rewrites the entry; tag-driven\n * invalidation is unaffected because tag state is checked remotely on every\n * read regardless of where the entry bytes came from.\n */\nconst LOCAL_ENTRY_TTL_MS = 5 * 60_000;\nconst LOCAL_CACHE_MAX_ENTRIES = 256;\nconst LOCAL_CACHE_MAX_TOTAL_BYTES = 64 * 1024 * 1024;\nconst LOCAL_CACHE_MAX_ENTRY_BYTES = 8 * 1024 * 1024;\n\ninterface LocalCacheSlot {\n entry: IncrementalCacheEntry;\n cachedAt: number;\n bytes: number;\n}\n\nconst approximateEntryBytes = (entry: IncrementalCacheEntry): number => {\n try {\n return JSON.stringify(entry)?.length ?? LOCAL_CACHE_MAX_ENTRY_BYTES + 1;\n } catch {\n // Circular or otherwise unserializable values are never cached locally.\n return LOCAL_CACHE_MAX_ENTRY_BYTES + 1;\n }\n};\n\n/**\n * Byte-bounded in-process LRU in front of the remote entry store.\n *\n * The remote store is an HTTP service backed by object storage, so every miss\n * costs a network round trip — and when that store degrades, page renders\n * degrade with it (a production incident showed second-level blob latency\n * turning every render of a cached page into a multi-second response).\n * Serving entry bytes locally removes that dependency from the hot path while\n * the per-read remote tag-state check keeps `revalidateTag` authoritative.\n */\nclass LocalEntryCache {\n private readonly slots = new Map<string, LocalCacheSlot>();\n private totalBytes = 0;\n\n get(key: string): IncrementalCacheEntry | undefined {\n const slot = this.slots.get(key);\n if (!slot) return undefined;\n if (Date.now() - slot.cachedAt > LOCAL_ENTRY_TTL_MS) {\n this.delete(key);\n return undefined;\n }\n // Refresh recency for LRU eviction.\n this.slots.delete(key);\n this.slots.set(key, slot);\n return slot.entry;\n }\n\n set(key: string, entry: IncrementalCacheEntry): void {\n const bytes = approximateEntryBytes(entry);\n if (bytes > LOCAL_CACHE_MAX_ENTRY_BYTES) {\n this.delete(key);\n return;\n }\n this.delete(key);\n this.slots.set(key, { entry, cachedAt: Date.now(), bytes });\n this.totalBytes += bytes;\n while (this.slots.size > LOCAL_CACHE_MAX_ENTRIES || this.totalBytes > LOCAL_CACHE_MAX_TOTAL_BYTES) {\n const oldest = this.slots.keys().next().value;\n if (oldest === undefined) break;\n this.delete(oldest);\n }\n }\n\n delete(key: string): void {\n const slot = this.slots.get(key);\n if (!slot) return;\n this.slots.delete(key);\n this.totalBytes -= slot.bytes;\n }\n\n clear(): void {\n this.slots.clear();\n this.totalBytes = 0;\n }\n}\n\nconst localEntries = new LocalEntryCache();\n\n/** Test-only: the local entry cache is process-wide, so suites must isolate it. */\nexport const clearLocalEntryCacheForTesting = (): void => localEntries.clear();\n\n/** Shared Network cache handler for ISR, server responses, fetches, and image metadata. */\nexport default class GigadriveNextCacheHandler {\n private readonly buildEntries = new Map<string, IncrementalCacheEntry>();\n /**\n * Next's own on-disk reader, pointed at the build output that ships inside the\n * deployment bundle (`writeStandaloneDirectory` recursively copies\n * `.next/server/{app,pages}`). Injecting a `cacheHandler` replaces Next's\n * FileSystemCache outright, which would otherwise strand every build-time\n * prerender and force a cold re-render of each page on first request.\n * Delegating to Next's reader keeps us off its private on-disk format.\n */\n private buildOutputCache?: Promise<FileSystemCacheLike | undefined>;\n private readonly context: CacheHandlerConstructorContext;\n\n constructor(context: CacheHandlerConstructorContext = {}) {\n this.context = context;\n }\n\n /**\n * Loads Next's on-disk reader lazily, memoized across requests. A Next release\n * that moves or renames the module degrades to \"no build-output fallback\" —\n * the remote cache still serves everything that has been regenerated.\n */\n private loadBuildOutputCache(): Promise<FileSystemCacheLike | undefined> {\n this.buildOutputCache ??= (async () => {\n if (!this.context.fs || !this.context.serverDistDir) return undefined;\n try {\n const module: unknown = await import('next/dist/server/lib/incremental-cache/file-system-cache.js');\n // Next ships this as CommonJS, so the constructor sits behind a different\n // number of `default` hops depending on whether this bundle was loaded as\n // CJS or ESM. Unwrap until a callable turns up rather than guessing.\n let candidate: unknown = module;\n for (let hop = 0; hop < 3 && candidate && typeof candidate !== 'function'; hop += 1) {\n candidate = (candidate as { default?: unknown }).default;\n }\n if (typeof candidate !== 'function') return undefined;\n const FileSystemCache = candidate as new (context: CacheHandlerConstructorContext) => FileSystemCacheLike;\n return new FileSystemCache(this.context);\n } catch {\n return undefined;\n }\n })();\n return this.buildOutputCache;\n }\n\n /**\n * Applies remote tag state to an entry.\n *\n * @returns the entry, a stale-marked copy, or `null` when a tag expired.\n */\n private async applyTagState(entry: IncrementalCacheEntry, tags: string[]): Promise<IncrementalCacheEntry | null> {\n if (tags.length === 0) return entry;\n const tagState = await getRuntimeCacheTagState('incremental', tags);\n if (tagState.expired > entry.lastModified) return null;\n return tagState.stale > entry.lastModified ? { ...entry, lastModified: 1 } : entry;\n }\n\n async get(key: string, context: IncrementalCacheContext = {}): Promise<IncrementalCacheEntry | null> {\n if (isBuildPhase()) {\n const buildEntry = this.buildEntries.get(key) ?? null;\n return isIncrementalCacheEntry(buildEntry) ? buildEntry : null;\n }\n\n const local = localEntries.get(key);\n if (local) {\n return this.applyTagState(local, collectTags(local.tags, local.value, context));\n }\n\n const remote = await readRuntimeCache('incremental', key);\n if (isIncrementalCacheEntry(remote)) {\n localEntries.set(key, remote);\n return this.applyTagState(remote, collectTags(remote.tags, remote.value, context));\n }\n\n // Nothing regenerated yet: fall back to the build-time prerender shipped in\n // the bundle. Tag expiry is still resolved against the remote index — Next's\n // reader only knows its own in-process tag manifest, which is always empty\n // here, so trusting it would resurrect content after a `revalidateTag`.\n const buildOutputCache = await this.loadBuildOutputCache();\n const fromDisk = await buildOutputCache?.get(key, context).catch(() => null);\n if (!isIncrementalCacheEntry(fromDisk)) return null;\n return this.applyTagState(fromDisk, collectTags(fromDisk.tags, fromDisk.value, context));\n }\n\n async set(key: string, data: unknown, context: IncrementalCacheContext): Promise<void> {\n const tags = collectTags(undefined, data, context);\n const entry = { lastModified: Date.now(), value: data, tags, cacheControl: context.cacheControl };\n if (isBuildPhase()) {\n this.buildEntries.set(key, entry);\n return;\n }\n localEntries.set(key, entry);\n try {\n await writeRuntimeCache('incremental', key, entry, tags);\n } catch (error) {\n // The local copy would outlive a failed durable write and mask it from\n // this instance for the whole TTL; drop it so reads retry remotely.\n localEntries.delete(key);\n throw error;\n }\n }\n\n async revalidateTag(tags: string | string[], durations?: { expire?: number }): Promise<void> {\n const normalizedTags = Array.isArray(tags) ? tags : [tags];\n if (isBuildPhase()) {\n for (const [key, entry] of this.buildEntries) {\n if (entry.tags?.some((tag) => normalizedTags.includes(tag))) this.buildEntries.delete(key);\n }\n return;\n }\n await revalidateRuntimeCacheTags('incremental', normalizedTags, durations);\n }\n\n resetRequestCache(): void {}\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gigadrive/network-config",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.6",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/Gigadrive/sdk.git",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@types/node": "^24.13.3",
|
|
58
58
|
"effect": "^3.19.17",
|
|
59
59
|
"esbuild": "^0.28.0",
|
|
60
|
-
"next": "16.2.
|
|
60
|
+
"next": "16.2.12"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"@effect/platform": "^0.94.5 || ^0.96.0",
|