@gigadrive/network-config 3.4.17 → 4.0.0

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.
@@ -1,90 +0,0 @@
1
- // Template for the generated Edge runtime wrapper, which speaks the Web
2
- // `fetch(Request) -> Response` contract expected by the edge gateway. The
3
- // quoted `__GIGADRIVE_*__` tokens are replaced with JSON-encoded values and
4
- // the `__GIGADRIVE_EDGE_IMPORTS__` marker line is replaced with the ordered
5
- // chunk imports by `writeEntrypointWrappers` in nextjs-adapter.ts. Keep the
6
- // fetch export in sync with node-middleware-web.mjs (asserted by
7
- // nextjs-adapter.test.ts).
8
- import { persistPprCacheEntry } from '__GIGADRIVE_PPR_RUNTIME__';
9
- import { AsyncLocalStorage } from 'node:async_hooks';
10
-
11
- // Next's edge chunks must evaluate lazily on the first request, not at module
12
- // scope: chunk evaluation can block on runtime facilities that only exist once
13
- // the guest server is up, and an eager top-level await would keep the process
14
- // from ever reaching its listening state (observed as a MicroVM boot loop in
15
- // prod). The promise is shared, so evaluation still happens exactly once.
16
- let handlerPromise;
17
- const resolveHandler = () =>
18
- (handlerPromise ??= (async () => {
19
- globalThis.self ??= globalThis;
20
- globalThis.AsyncLocalStorage ??= AsyncLocalStorage;
21
- /* __GIGADRIVE_EDGE_IMPORTS__ */
22
- const registry = globalThis._ENTRIES;
23
- if (!registry) throw new Error('Next.js edge entry registry is unavailable');
24
- const entry = await registry['__GIGADRIVE_EDGE_ENTRY_KEY__'];
25
- const handler = entry?.['__GIGADRIVE_EDGE_HANDLER_EXPORT__'];
26
- if (typeof handler !== 'function') throw new Error('Next.js edge handler is unavailable');
27
- return handler;
28
- })());
29
-
30
- export async function fetch(request) {
31
- const nextHandler = await resolveHandler();
32
- const pending = [];
33
- const url = new URL(request.url);
34
- const response = await nextHandler(request, {
35
- signal: request.signal,
36
- waitUntil(promise) {
37
- pending.push(Promise.resolve(promise));
38
- },
39
- requestMeta: {
40
- hostname: url.hostname,
41
- invocationTarget: request.headers.get('x-gigadrive-next-invocation-target') ?? url.pathname,
42
- routeMatches: Object.fromEntries(new URLSearchParams(request.headers.get('x-now-route-matches') ?? '')),
43
- relativeProjectDir: '__GIGADRIVE_RELATIVE_PROJECT_DIR__',
44
- onCacheEntryV2(cacheEntry, meta) {
45
- pending.push(
46
- persistPprCacheEntry(
47
- request.headers.get('x-gigadrive-next-cache-key') ??
48
- meta.url ??
49
- request.headers.get('x-matched-path') ??
50
- url.pathname,
51
- cacheEntry
52
- )
53
- );
54
- return false;
55
- },
56
- },
57
- });
58
- if (!response.body) {
59
- await Promise.allSettled(pending);
60
- return response;
61
- }
62
- const reader = response.body.getReader();
63
- const body = new ReadableStream({
64
- async pull(controller) {
65
- let result;
66
- try {
67
- result = await reader.read();
68
- } catch (error) {
69
- // A failing upstream read must still settle queued waitUntil work
70
- // (e.g. PPR cache persistence) before the invocation ends.
71
- await Promise.allSettled(pending);
72
- throw error;
73
- }
74
- if (result.done) {
75
- await Promise.allSettled(pending);
76
- controller.close();
77
- return;
78
- }
79
- controller.enqueue(result.value);
80
- },
81
- async cancel(reason) {
82
- try {
83
- await reader.cancel(reason);
84
- } finally {
85
- await Promise.allSettled(pending);
86
- }
87
- },
88
- });
89
- return new Response(body, response);
90
- }
@@ -1,98 +0,0 @@
1
- // Template for the generated Node middleware wrapper, which speaks the Web
2
- // `fetch(Request) -> Response` contract expected by the edge gateway. The
3
- // quoted `__GIGADRIVE_*__` tokens are replaced with JSON-encoded values by
4
- // `writeEntrypointWrappers` in nextjs-adapter.ts. Keep the handler resolution
5
- // block in sync with node-route.mjs and the fetch export in sync with
6
- // edge-web.mjs (both are asserted by nextjs-adapter.test.ts).
7
- import { persistPprCacheEntry } from '__GIGADRIVE_PPR_RUNTIME__';
8
- import { fileURLToPath } from 'node:url';
9
-
10
- // The Next server resolves configured cache handlers and build manifests
11
- // relative to the process working directory, so monorepo deployments must run
12
- // from the project directory rather than the repository root. The chdir runs
13
- // exactly once at module evaluation — never per request — so concurrent
14
- // invocations cannot race on process-global state.
15
- process.chdir(fileURLToPath(new URL('__GIGADRIVE_PROJECT_DIR__', import.meta.url)));
16
-
17
- // The Next entrypoint must be imported lazily on the first request, not with a
18
- // top-level await: some route module graphs block on facilities that only
19
- // exist once the guest server is listening, and eager evaluation deadlocks the
20
- // boot (observed as MicroVM boot loops in prod). The promise is shared, so the
21
- // module still evaluates exactly once.
22
- let handlerPromise;
23
- const resolveHandler = () =>
24
- (handlerPromise ??= (async () => {
25
- const nextEntrypoint = await import('__GIGADRIVE_ENTRYPOINT__');
26
- // Turbopack builds may export the module (or its default) as a promise.
27
- const loadedEntrypoint = await Promise.resolve(nextEntrypoint.default ?? nextEntrypoint);
28
- const handler =
29
- nextEntrypoint.handler ??
30
- loadedEntrypoint?.handler ??
31
- loadedEntrypoint?.default?.handler ??
32
- loadedEntrypoint?.default ??
33
- loadedEntrypoint;
34
- if (typeof handler !== 'function') throw new Error('Next.js middleware handler is unavailable');
35
- return handler;
36
- })());
37
-
38
- export async function fetch(request) {
39
- const nextHandler = await resolveHandler();
40
- const pending = [];
41
- const url = new URL(request.url);
42
- const response = await nextHandler(request, {
43
- signal: request.signal,
44
- waitUntil(promise) {
45
- pending.push(Promise.resolve(promise));
46
- },
47
- requestMeta: {
48
- hostname: url.hostname,
49
- invocationTarget: request.headers.get('x-gigadrive-next-invocation-target') ?? url.pathname,
50
- routeMatches: Object.fromEntries(new URLSearchParams(request.headers.get('x-now-route-matches') ?? '')),
51
- relativeProjectDir: '__GIGADRIVE_RELATIVE_PROJECT_DIR__',
52
- onCacheEntryV2(cacheEntry, meta) {
53
- pending.push(
54
- persistPprCacheEntry(
55
- request.headers.get('x-gigadrive-next-cache-key') ??
56
- meta.url ??
57
- request.headers.get('x-matched-path') ??
58
- url.pathname,
59
- cacheEntry
60
- )
61
- );
62
- return false;
63
- },
64
- },
65
- });
66
- if (!response.body) {
67
- await Promise.allSettled(pending);
68
- return response;
69
- }
70
- const reader = response.body.getReader();
71
- const body = new ReadableStream({
72
- async pull(controller) {
73
- let result;
74
- try {
75
- result = await reader.read();
76
- } catch (error) {
77
- // A failing upstream read must still settle queued waitUntil work
78
- // (e.g. PPR cache persistence) before the invocation ends.
79
- await Promise.allSettled(pending);
80
- throw error;
81
- }
82
- if (result.done) {
83
- await Promise.allSettled(pending);
84
- controller.close();
85
- return;
86
- }
87
- controller.enqueue(result.value);
88
- },
89
- async cancel(reason) {
90
- try {
91
- await reader.cancel(reason);
92
- } finally {
93
- await Promise.allSettled(pending);
94
- }
95
- },
96
- });
97
- return new Response(body, response);
98
- }
@@ -1,73 +0,0 @@
1
- // Template for the generated Node route-handler wrapper. The quoted
2
- // `__GIGADRIVE_*__` tokens are replaced with JSON-encoded values by
3
- // `writeEntrypointWrappers` in nextjs-adapter.ts before the file is written
4
- // into `.gigadrive/nextjs/entrypoints/`. Keep the request contract in sync
5
- // with node-middleware-web.mjs (the handler resolution block is asserted to
6
- // stay identical by nextjs-adapter.test.ts).
7
- import { persistPprCacheEntry, revalidateNextPath } from '__GIGADRIVE_PPR_RUNTIME__';
8
- import 'next/dist/build/adapter/setup-node-env.external.js';
9
- import { fileURLToPath } from 'node:url';
10
-
11
- // The Next server resolves configured cache handlers and build manifests
12
- // relative to the process working directory, so monorepo deployments must run
13
- // from the project directory rather than the repository root. The chdir runs
14
- // exactly once at module evaluation — never per request — so concurrent
15
- // invocations cannot race on process-global state.
16
- process.chdir(fileURLToPath(new URL('__GIGADRIVE_PROJECT_DIR__', import.meta.url)));
17
-
18
- // The Next entrypoint must be imported lazily on the first request, not with a
19
- // top-level await: some route module graphs block on facilities that only
20
- // exist once the guest server is listening, and eager evaluation deadlocks the
21
- // boot (observed as MicroVM boot loops in prod). The promise is shared, so the
22
- // module still evaluates exactly once.
23
- let handlerPromise;
24
- const resolveHandler = () =>
25
- (handlerPromise ??= (async () => {
26
- const nextEntrypoint = await import('__GIGADRIVE_ENTRYPOINT__');
27
- // Turbopack builds may export the module (or its default) as a promise.
28
- const loadedEntrypoint = await Promise.resolve(nextEntrypoint.default ?? nextEntrypoint);
29
- const handler =
30
- nextEntrypoint.handler ??
31
- loadedEntrypoint?.handler ??
32
- loadedEntrypoint?.default?.handler ??
33
- loadedEntrypoint?.default ??
34
- loadedEntrypoint;
35
- if (typeof handler !== 'function') throw new Error('Next.js Node handler is unavailable');
36
- return handler;
37
- })());
38
-
39
- export default async function handler(req, res) {
40
- const nextHandler = await resolveHandler();
41
- const pending = [];
42
- const hostname = Array.isArray(req.headers.host) ? req.headers.host[0] : req.headers.host;
43
- await nextHandler(req, res, {
44
- waitUntil(promise) {
45
- pending.push(Promise.resolve(promise));
46
- },
47
- requestMeta: {
48
- hostname,
49
- invocationTarget: req.headers['x-gigadrive-next-invocation-target'] ?? req.url,
50
- routeMatches: Object.fromEntries(new URLSearchParams(req.headers['x-now-route-matches'] ?? '')),
51
- relativeProjectDir: '__GIGADRIVE_RELATIVE_PROJECT_DIR__',
52
- revalidate(input) {
53
- return revalidateNextPath({ ...input, hostname });
54
- },
55
- onCacheEntryV2(cacheEntry, meta) {
56
- const cacheKey = req.headers['x-gigadrive-next-cache-key'];
57
- const matchedPath = req.headers['x-matched-path'];
58
- pending.push(
59
- persistPprCacheEntry(
60
- (Array.isArray(cacheKey) ? cacheKey[0] : cacheKey) ??
61
- meta.url ??
62
- (Array.isArray(matchedPath) ? matchedPath[0] : matchedPath) ??
63
- req.url ??
64
- '/',
65
- cacheEntry
66
- )
67
- );
68
- return false;
69
- },
70
- },
71
- });
72
- await Promise.allSettled(pending);
73
- }
@@ -1,46 +0,0 @@
1
- interface ResponseCacheEntry {
2
- cacheControl?: unknown;
3
- value?: {
4
- kind?: unknown;
5
- html?: unknown;
6
- postponed?: unknown;
7
- headers?: unknown;
8
- status?: unknown;
9
- } | null;
10
- }
11
- interface NextInternalRevalidateInput {
12
- urlPath: string;
13
- headers: Record<string, string>;
14
- opts: {
15
- unstable_onlyGenerated?: boolean;
16
- };
17
- hostname: string | undefined;
18
- }
19
- /**
20
- * Persists the atomic shell/postponed pair emitted by Next's PPR response cache.
21
- *
22
- * @param cacheKey - The response-cache URL or pathname associated with the PPR entry.
23
- * @param cacheEntry - The Next response-cache entry emitted by `onCacheEntryV2`.
24
- * @returns A promise that settles after the entry is written, or immediately for unsupported entries.
25
- *
26
- * @example
27
- * ```ts
28
- * await persistPprCacheEntry('/products/one', {
29
- * value: { kind: 'APP_PAGE', html: '<html>shell</html>', postponed: 'opaque-state' },
30
- * });
31
- * ```
32
- */
33
- declare const persistPprCacheEntry: (cacheKey: string, cacheEntry: ResponseCacheEntry) => Promise<void>;
34
- /**
35
- * Runs Next's synchronous Pages Router on-demand revalidation protocol.
36
- *
37
- * The CDN path is evicted before a cache-busting request reaches the split page
38
- * function. Next then regenerates the shared incremental-cache entry before this
39
- * promise resolves, preserving the blocking semantics of `response.revalidate()`.
40
- *
41
- * @param input - The internal revalidation request emitted by Next's Pages API runtime.
42
- * @returns A promise that settles after Next has regenerated the requested path.
43
- */
44
- declare const revalidateNextPath: (input: NextInternalRevalidateInput) => Promise<void>;
45
-
46
- export { persistPprCacheEntry, revalidateNextPath };
@@ -1,46 +0,0 @@
1
- interface ResponseCacheEntry {
2
- cacheControl?: unknown;
3
- value?: {
4
- kind?: unknown;
5
- html?: unknown;
6
- postponed?: unknown;
7
- headers?: unknown;
8
- status?: unknown;
9
- } | null;
10
- }
11
- interface NextInternalRevalidateInput {
12
- urlPath: string;
13
- headers: Record<string, string>;
14
- opts: {
15
- unstable_onlyGenerated?: boolean;
16
- };
17
- hostname: string | undefined;
18
- }
19
- /**
20
- * Persists the atomic shell/postponed pair emitted by Next's PPR response cache.
21
- *
22
- * @param cacheKey - The response-cache URL or pathname associated with the PPR entry.
23
- * @param cacheEntry - The Next response-cache entry emitted by `onCacheEntryV2`.
24
- * @returns A promise that settles after the entry is written, or immediately for unsupported entries.
25
- *
26
- * @example
27
- * ```ts
28
- * await persistPprCacheEntry('/products/one', {
29
- * value: { kind: 'APP_PAGE', html: '<html>shell</html>', postponed: 'opaque-state' },
30
- * });
31
- * ```
32
- */
33
- declare const persistPprCacheEntry: (cacheKey: string, cacheEntry: ResponseCacheEntry) => Promise<void>;
34
- /**
35
- * Runs Next's synchronous Pages Router on-demand revalidation protocol.
36
- *
37
- * The CDN path is evicted before a cache-busting request reaches the split page
38
- * function. Next then regenerates the shared incremental-cache entry before this
39
- * promise resolves, preserving the blocking semantics of `response.revalidate()`.
40
- *
41
- * @param input - The internal revalidation request emitted by Next's Pages API runtime.
42
- * @returns A promise that settles after Next has regenerated the requested path.
43
- */
44
- declare const revalidateNextPath: (input: NextInternalRevalidateInput) => Promise<void>;
45
-
46
- export { persistPprCacheEntry, revalidateNextPath };
@@ -1,177 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/nextjs-ppr-runtime.ts
21
- var nextjs_ppr_runtime_exports = {};
22
- __export(nextjs_ppr_runtime_exports, {
23
- persistPprCacheEntry: () => persistPprCacheEntry,
24
- revalidateNextPath: () => revalidateNextPath
25
- });
26
- module.exports = __toCommonJS(nextjs_ppr_runtime_exports);
27
-
28
- // src/nextjs-runtime-cache-client.ts
29
- var cachedToken;
30
- var apiBaseUrl = () => (process.env.GIGADRIVE_API_URL ?? "https://api.gigadrive.network").replace(/\/$/, "");
31
- var encodeBinary = (value, seen = /* @__PURE__ */ new WeakSet()) => {
32
- if (value instanceof Uint8Array) {
33
- return { __gigadriveType: "bytes", value: Buffer.from(value).toString("base64") };
34
- }
35
- if (value instanceof ArrayBuffer) {
36
- return { __gigadriveType: "bytes", value: Buffer.from(value).toString("base64") };
37
- }
38
- if (Array.isArray(value)) return value.map((item) => encodeBinary(item, seen));
39
- if (typeof value !== "object" || value === null) return value;
40
- if (seen.has(value)) throw new Error("Next.js cache entry contains a circular value");
41
- seen.add(value);
42
- const result = {};
43
- for (const [key, item] of Object.entries(value)) result[key] = encodeBinary(item, seen);
44
- seen.delete(value);
45
- return result;
46
- };
47
- var getAccessToken = async () => {
48
- if (cachedToken && cachedToken.expiresAt > Date.now() + 3e4) return cachedToken.value;
49
- const clientId = process.env.GIGADRIVE_CLIENT_ID;
50
- const clientSecret = process.env.GIGADRIVE_CLIENT_SECRET;
51
- if (!clientId || !clientSecret) throw new Error("Gigadrive workload credentials are unavailable");
52
- const response = await fetch(`${apiBaseUrl()}/oauth2/token`, {
53
- method: "POST",
54
- headers: {
55
- authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
56
- "content-type": "application/x-www-form-urlencoded"
57
- },
58
- body: "grant_type=client_credentials"
59
- });
60
- if (!response.ok) throw new Error(`Gigadrive workload authentication failed with status ${response.status}`);
61
- const token = await response.json();
62
- if (!token.access_token) throw new Error("Gigadrive workload authentication returned no access token");
63
- cachedToken = {
64
- value: token.access_token,
65
- expiresAt: Date.now() + Math.max(60, token.expires_in ?? 300) * 1e3
66
- };
67
- return token.access_token;
68
- };
69
- var request = async (pathname, init, attempt = 0) => {
70
- const token = await getAccessToken();
71
- try {
72
- const response = await fetch(`${apiBaseUrl()}${pathname}`, {
73
- ...init,
74
- headers: {
75
- authorization: `Bearer ${token}`,
76
- "content-type": "application/json",
77
- "x-gigadrive-deployment-id": process.env.GIGADRIVE_DEPLOYMENT_ID ?? process.env.NEBULA_DEPLOYMENT_ID ?? "",
78
- "x-gigadrive-build-id": process.env.NEXT_BUILD_ID ?? "",
79
- ...init.headers
80
- }
81
- });
82
- if (response.status === 401 && attempt === 0) {
83
- cachedToken = void 0;
84
- return request(pathname, init, attempt + 1);
85
- }
86
- if (response.status >= 500 && attempt < 2) return request(pathname, init, attempt + 1);
87
- return response;
88
- } catch (error) {
89
- if (attempt < 2) return request(pathname, init, attempt + 1);
90
- throw error;
91
- }
92
- };
93
- var cachePath = (kind, key) => `/internal/runtime-cache/v1/entries/${encodeURIComponent(kind)}/${encodeURIComponent(key)}`;
94
- var writeRuntimeCache = async (kind, key, value, tags = []) => {
95
- const response = await request(cachePath(kind, key), {
96
- method: "PUT",
97
- body: JSON.stringify({ value: encodeBinary(value), tags })
98
- });
99
- if (!response.ok) throw new Error(`Gigadrive runtime cache write failed with status ${response.status}`);
100
- };
101
- var revalidateRuntimeCacheTags = async (kind, tags, durations) => {
102
- const response = await request("/internal/runtime-cache/v1/tags/revalidate", {
103
- method: "POST",
104
- body: JSON.stringify({ kind, tags, durations })
105
- });
106
- if (!response.ok) throw new Error(`Gigadrive runtime cache revalidation failed with status ${response.status}`);
107
- };
108
-
109
- // src/nextjs-ppr-runtime.ts
110
- var normalizeHeaders = (value) => {
111
- if (typeof value !== "object" || value === null || Array.isArray(value)) return {};
112
- const headers = {};
113
- for (const [name, item] of Object.entries(value)) {
114
- if (typeof item === "string" || typeof item === "number") headers[name] = String(item);
115
- else if (Array.isArray(item) && item.every((entry) => typeof entry === "string" || typeof entry === "number")) {
116
- headers[name] = item.map(String);
117
- }
118
- }
119
- return headers;
120
- };
121
- var normalizeCacheKey = (value) => {
122
- try {
123
- const url = new URL(value, "https://gigadrive.invalid");
124
- return `${url.pathname || "/"}${url.search}`;
125
- } catch {
126
- return value.startsWith("/") ? value : `/${value}`;
127
- }
128
- };
129
- var readShell = (value) => {
130
- if (typeof value === "string") return value;
131
- if (typeof value !== "object" || value === null) return null;
132
- const toUnchunkedString = value.toUnchunkedString;
133
- return typeof toUnchunkedString === "function" ? String(toUnchunkedString.call(value)) : null;
134
- };
135
- var persistPprCacheEntry = async (cacheKey, cacheEntry) => {
136
- if (cacheEntry.value?.kind !== "APP_PAGE") return;
137
- const shell = readShell(cacheEntry.value.html);
138
- if (shell === null) return;
139
- const headers = normalizeHeaders(cacheEntry.value.headers);
140
- const tags = (headers["x-next-cache-tags"] ?? []).toString().split(",").map((tag) => tag.trim()).filter(Boolean);
141
- const value = {
142
- shell,
143
- ...typeof cacheEntry.value.postponed === "string" ? { postponedState: cacheEntry.value.postponed } : {},
144
- headers,
145
- ...typeof cacheEntry.value.status === "number" ? { status: cacheEntry.value.status } : {},
146
- ...cacheEntry.cacheControl === void 0 ? {} : { cacheControl: cacheEntry.cacheControl }
147
- };
148
- await writeRuntimeCache("incremental", `ppr:${normalizeCacheKey(cacheKey)}`, value, tags);
149
- };
150
- var revalidateNextPath = async (input) => {
151
- if (!input.urlPath.startsWith("/")) throw new Error("Next.js revalidation requires an absolute application path");
152
- if (!input.hostname) throw new Error("Next.js revalidation requires the application hostname");
153
- const pathname = new URL(input.urlPath, "https://gigadrive.invalid").pathname;
154
- await revalidateRuntimeCacheTags("incremental", [`path:${pathname}`]);
155
- const origin = process.env.GIGADRIVE_APPLICATION_ORIGIN ?? `https://${input.hostname}`;
156
- const originUrl = new URL(origin);
157
- if (originUrl.protocol !== "https:" && originUrl.protocol !== "http:") {
158
- throw new Error("Next.js revalidation requires an HTTP application origin");
159
- }
160
- const url = new URL(input.urlPath, originUrl);
161
- if (url.origin !== originUrl.origin)
162
- throw new Error("Next.js revalidation path must remain on the application origin");
163
- url.searchParams.set("__gigadrive_revalidate", `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`);
164
- const headers = new Headers(input.headers);
165
- headers.set("cache-control", "no-cache");
166
- const response = await fetch(url, { method: "HEAD", headers, redirect: "manual" });
167
- const cacheStatus = response.headers.get("x-gigadrive-cache") ?? response.headers.get("x-nextjs-cache");
168
- if (cacheStatus?.toUpperCase() !== "REVALIDATED" && response.status !== 200 && !(response.status === 404 && input.opts.unstable_onlyGenerated)) {
169
- throw new Error(`Next.js revalidation failed with status ${response.status}`);
170
- }
171
- };
172
- // Annotate the CommonJS export names for ESM import in node:
173
- 0 && (module.exports = {
174
- persistPprCacheEntry,
175
- revalidateNextPath
176
- });
177
- //# sourceMappingURL=nextjs-ppr-runtime.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/nextjs-ppr-runtime.ts","../src/nextjs-runtime-cache-client.ts"],"sourcesContent":["import { revalidateRuntimeCacheTags, writeRuntimeCache } from './nextjs-runtime-cache-client';\n\ninterface ResponseCacheEntry {\n cacheControl?: unknown;\n value?: {\n kind?: unknown;\n html?: unknown;\n postponed?: unknown;\n headers?: unknown;\n status?: unknown;\n } | null;\n}\n\ninterface PersistedPprCacheEntry {\n shell: string;\n postponedState?: string;\n headers: Record<string, string | string[]>;\n status?: number;\n cacheControl?: unknown;\n}\n\ninterface NextInternalRevalidateInput {\n urlPath: string;\n headers: Record<string, string>;\n opts: { unstable_onlyGenerated?: boolean };\n hostname: string | undefined;\n}\n\nconst normalizeHeaders = (value: unknown): Record<string, string | string[]> => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return {};\n const headers: Record<string, string | string[]> = {};\n for (const [name, item] of Object.entries(value)) {\n if (typeof item === 'string' || typeof item === 'number') headers[name] = String(item);\n else if (Array.isArray(item) && item.every((entry) => typeof entry === 'string' || typeof entry === 'number')) {\n headers[name] = item.map(String);\n }\n }\n return headers;\n};\n\nconst normalizeCacheKey = (value: string): string => {\n try {\n const url = new URL(value, 'https://gigadrive.invalid');\n return `${url.pathname || '/'}${url.search}`;\n } catch {\n return value.startsWith('/') ? value : `/${value}`;\n }\n};\n\nconst readShell = (value: unknown): string | null => {\n if (typeof value === 'string') return value;\n if (typeof value !== 'object' || value === null) return null;\n const toUnchunkedString = (value as { toUnchunkedString?: unknown }).toUnchunkedString;\n return typeof toUnchunkedString === 'function' ? String(toUnchunkedString.call(value)) : null;\n};\n\n/**\n * Persists the atomic shell/postponed pair emitted by Next's PPR response cache.\n *\n * @param cacheKey - The response-cache URL or pathname associated with the PPR entry.\n * @param cacheEntry - The Next response-cache entry emitted by `onCacheEntryV2`.\n * @returns A promise that settles after the entry is written, or immediately for unsupported entries.\n *\n * @example\n * ```ts\n * await persistPprCacheEntry('/products/one', {\n * value: { kind: 'APP_PAGE', html: '<html>shell</html>', postponed: 'opaque-state' },\n * });\n * ```\n */\nexport const persistPprCacheEntry = async (cacheKey: string, cacheEntry: ResponseCacheEntry): Promise<void> => {\n if (cacheEntry.value?.kind !== 'APP_PAGE') return;\n const shell = readShell(cacheEntry.value.html);\n if (shell === null) return;\n\n const headers = normalizeHeaders(cacheEntry.value.headers);\n const tags = (headers['x-next-cache-tags'] ?? [])\n .toString()\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean);\n const value: PersistedPprCacheEntry = {\n shell,\n ...(typeof cacheEntry.value.postponed === 'string' ? { postponedState: cacheEntry.value.postponed } : {}),\n headers,\n ...(typeof cacheEntry.value.status === 'number' ? { status: cacheEntry.value.status } : {}),\n ...(cacheEntry.cacheControl === undefined ? {} : { cacheControl: cacheEntry.cacheControl }),\n };\n\n await writeRuntimeCache('incremental', `ppr:${normalizeCacheKey(cacheKey)}`, value, tags);\n};\n\n/**\n * Runs Next's synchronous Pages Router on-demand revalidation protocol.\n *\n * The CDN path is evicted before a cache-busting request reaches the split page\n * function. Next then regenerates the shared incremental-cache entry before this\n * promise resolves, preserving the blocking semantics of `response.revalidate()`.\n *\n * @param input - The internal revalidation request emitted by Next's Pages API runtime.\n * @returns A promise that settles after Next has regenerated the requested path.\n */\nexport const revalidateNextPath = async (input: NextInternalRevalidateInput): Promise<void> => {\n if (!input.urlPath.startsWith('/')) throw new Error('Next.js revalidation requires an absolute application path');\n if (!input.hostname) throw new Error('Next.js revalidation requires the application hostname');\n\n const pathname = new URL(input.urlPath, 'https://gigadrive.invalid').pathname;\n await revalidateRuntimeCacheTags('incremental', [`path:${pathname}`]);\n\n const origin = process.env.GIGADRIVE_APPLICATION_ORIGIN ?? `https://${input.hostname}`;\n const originUrl = new URL(origin);\n if (originUrl.protocol !== 'https:' && originUrl.protocol !== 'http:') {\n throw new Error('Next.js revalidation requires an HTTP application origin');\n }\n const url = new URL(input.urlPath, originUrl);\n if (url.origin !== originUrl.origin)\n throw new Error('Next.js revalidation path must remain on the application origin');\n url.searchParams.set('__gigadrive_revalidate', `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`);\n\n const headers = new Headers(input.headers);\n headers.set('cache-control', 'no-cache');\n const response = await fetch(url, { method: 'HEAD', headers, redirect: 'manual' });\n // Prefer the platform-owned cache-status header; fall back to the header Next\n // itself emits. Never rely on CDN-vendor header names here.\n const cacheStatus = response.headers.get('x-gigadrive-cache') ?? response.headers.get('x-nextjs-cache');\n if (\n cacheStatus?.toUpperCase() !== 'REVALIDATED' &&\n response.status !== 200 &&\n !(response.status === 404 && input.opts.unstable_onlyGenerated)\n ) {\n throw new Error(`Next.js revalidation failed with status ${response.status}`);\n }\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 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 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"],"mappings":"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","names":[]}