vinext 1.0.0-beta.1 → 1.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/build/client-build-config.js +8 -1
- package/dist/build/report.d.ts +8 -1
- package/dist/build/report.js +12 -2
- package/dist/check.js +19 -2
- package/dist/cli.js +3 -2
- package/dist/config/config-matchers.d.ts +13 -37
- package/dist/config/config-matchers.js +35 -122
- package/dist/config/next-config.d.ts +15 -5
- package/dist/config/next-config.js +7 -1
- package/dist/config/request-context.d.ts +14 -0
- package/dist/config/request-context.js +26 -0
- package/dist/entries/app-browser-entry.d.ts +4 -10
- package/dist/entries/app-browser-entry.js +20 -4
- package/dist/entries/app-rsc-entry.js +30 -9
- package/dist/entries/app-rsc-manifest.js +36 -0
- package/dist/entries/pages-client-entry.js +0 -1
- package/dist/entries/pages-server-entry.js +13 -5
- package/dist/index.js +194 -101
- package/dist/init-cloudflare.d.ts +3 -1
- package/dist/init-cloudflare.js +59 -5
- package/dist/init.d.ts +6 -4
- package/dist/init.js +20 -22
- package/dist/plugins/extensionless-dynamic-import.js +23 -18
- package/dist/plugins/ignore-dynamic-requests.js +3 -1
- package/dist/plugins/import-meta-url.js +17 -6
- package/dist/plugins/og-assets.js +1 -1
- package/dist/plugins/require-context.js +20 -15
- package/dist/plugins/transform-cache.d.ts +19 -0
- package/dist/plugins/transform-cache.js +36 -0
- package/dist/routing/app-route-graph.d.ts +27 -11
- package/dist/routing/app-route-graph.js +158 -22
- package/dist/routing/app-router.js +12 -6
- package/dist/routing/file-matcher.d.ts +11 -22
- package/dist/routing/file-matcher.js +21 -33
- package/dist/routing/pages-router.js +23 -29
- package/dist/routing/route-matching.d.ts +14 -1
- package/dist/routing/route-matching.js +13 -1
- package/dist/routing/route-pattern.d.ts +2 -1
- package/dist/routing/route-pattern.js +7 -4
- package/dist/routing/route-trie.d.ts +5 -1
- package/dist/routing/route-trie.js +5 -2
- package/dist/server/api-handler.d.ts +2 -0
- package/dist/server/api-handler.js +3 -3
- package/dist/server/app-browser-entry.js +110 -37
- package/dist/server/app-browser-history-controller.d.ts +1 -1
- package/dist/server/app-browser-history-controller.js +3 -3
- package/dist/server/app-browser-navigation-controller.d.ts +23 -21
- package/dist/server/app-browser-navigation-controller.js +2 -2
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +3 -0
- package/dist/server/app-fallback-renderer.js +4 -2
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-page-boundary-render.d.ts +12 -1
- package/dist/server/app-page-boundary-render.js +84 -2
- package/dist/server/app-page-cache-finalizer.d.ts +1 -1
- package/dist/server/app-page-cache-finalizer.js +1 -1
- package/dist/server/app-page-cache.d.ts +2 -2
- package/dist/server/app-page-cache.js +16 -2
- package/dist/server/app-page-dispatch.d.ts +19 -2
- package/dist/server/app-page-dispatch.js +45 -23
- package/dist/server/app-page-element-builder.d.ts +9 -2
- package/dist/server/app-page-element-builder.js +144 -33
- package/dist/server/app-page-head.d.ts +56 -4
- package/dist/server/app-page-head.js +216 -85
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +114 -0
- package/dist/server/app-page-probe.d.ts +4 -0
- package/dist/server/app-page-probe.js +6 -2
- package/dist/server/app-page-render.d.ts +2 -2
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-page-request.d.ts +15 -0
- package/dist/server/app-page-request.js +134 -14
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +16 -0
- package/dist/server/app-page-route-wiring.js +254 -52
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +2 -1
- package/dist/server/app-post-middleware-context.d.ts +1 -1
- package/dist/server/app-post-middleware-context.js +1 -1
- package/dist/server/app-route-handler-cache.js +4 -0
- package/dist/server/app-route-handler-dispatch.js +40 -20
- package/dist/server/app-route-handler-execution.d.ts +6 -1
- package/dist/server/app-route-handler-execution.js +42 -16
- package/dist/server/app-route-handler-policy.d.ts +2 -0
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-module-loader.d.ts +9 -1
- package/dist/server/app-route-module-loader.js +4 -0
- package/dist/server/app-router-entry.js +6 -3
- package/dist/server/app-rsc-cache-busting.d.ts +1 -1
- package/dist/server/app-rsc-errors.d.ts +1 -1
- package/dist/server/app-rsc-errors.js +22 -2
- package/dist/server/app-rsc-handler.d.ts +10 -5
- package/dist/server/app-rsc-handler.js +73 -33
- package/dist/server/app-rsc-request-normalization.d.ts +3 -2
- package/dist/server/app-rsc-request-normalization.js +8 -2
- package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
- package/dist/server/app-rsc-response-finalizer.js +5 -11
- package/dist/server/app-rsc-route-matching.d.ts +29 -0
- package/dist/server/app-rsc-route-matching.js +93 -11
- package/dist/server/app-segment-config.js +13 -3
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +9 -7
- package/dist/server/app-ssr-entry.js +6 -6
- package/dist/server/app-ssr-stream.d.ts +1 -7
- package/dist/server/app-ssr-stream.js +2 -10
- package/dist/server/cache-control.d.ts +2 -2
- package/dist/server/cache-control.js +2 -1
- package/dist/server/config-headers.d.ts +24 -0
- package/dist/server/config-headers.js +52 -0
- package/dist/server/dev-initial-server-error.d.ts +1 -1
- package/dist/server/dev-server.d.ts +3 -1
- package/dist/server/dev-server.js +170 -321
- package/dist/server/headers.d.ts +2 -2
- package/dist/server/headers.js +4 -3
- package/dist/server/isr-cache.d.ts +11 -34
- package/dist/server/isr-cache.js +33 -43
- package/dist/server/isr-decision.d.ts +2 -2
- package/dist/server/middleware-matcher-pattern.d.ts +22 -0
- package/dist/server/middleware-matcher-pattern.js +219 -0
- package/dist/server/middleware-matcher.d.ts +2 -7
- package/dist/server/middleware-matcher.js +13 -60
- package/dist/server/middleware-path-to-regexp.d.ts +14 -0
- package/dist/server/middleware-path-to-regexp.js +228 -0
- package/dist/server/middleware-runtime.js +4 -3
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +2 -1
- package/dist/server/pages-api-route.d.ts +2 -0
- package/dist/server/pages-api-route.js +4 -1
- package/dist/server/pages-data-route.d.ts +11 -1
- package/dist/server/pages-data-route.js +16 -1
- package/dist/server/pages-dev-hydration.js +0 -1
- package/dist/server/pages-get-initial-props.d.ts +16 -3
- package/dist/server/pages-get-initial-props.js +17 -10
- package/dist/server/pages-i18n.js +64 -16
- package/dist/server/pages-node-compat.d.ts +2 -0
- package/dist/server/pages-node-compat.js +7 -3
- package/dist/server/pages-page-data.d.ts +64 -10
- package/dist/server/pages-page-data.js +349 -80
- package/dist/server/pages-page-handler.d.ts +9 -3
- package/dist/server/pages-page-handler.js +131 -36
- package/dist/server/pages-page-response.d.ts +5 -3
- package/dist/server/pages-page-response.js +24 -27
- package/dist/server/pages-readiness.d.ts +3 -3
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +30 -12
- package/dist/server/pages-revalidate.d.ts +1 -1
- package/dist/server/pages-revalidate.js +54 -8
- package/dist/server/pages-router-entry.d.ts +1 -0
- package/dist/server/pages-router-entry.js +16 -4
- package/dist/server/prerender-route-params.js +2 -2
- package/dist/server/prod-server.d.ts +3 -5
- package/dist/server/prod-server.js +72 -35
- package/dist/server/request-pipeline.d.ts +15 -29
- package/dist/server/request-pipeline.js +24 -59
- package/dist/server/revalidation-host.d.ts +11 -0
- package/dist/server/revalidation-host.js +19 -0
- package/dist/server/rsc-stream-hints.js +122 -18
- package/dist/server/worker-revalidation-context.d.ts +13 -0
- package/dist/server/worker-revalidation-context.js +29 -0
- package/dist/shims/app.d.ts +1 -1
- package/dist/shims/cache-handler.d.ts +1 -1
- package/dist/shims/cache-handler.js +10 -7
- package/dist/shims/cache-request-state.d.ts +27 -1
- package/dist/shims/cache-request-state.js +60 -1
- package/dist/shims/cache-runtime.d.ts +18 -1
- package/dist/shims/cache-runtime.js +26 -8
- package/dist/shims/cache.d.ts +5 -5
- package/dist/shims/cache.js +27 -11
- package/dist/shims/document.d.ts +42 -83
- package/dist/shims/document.js +62 -53
- package/dist/shims/dynamic.d.ts +5 -25
- package/dist/shims/dynamic.js +29 -8
- package/dist/shims/error.d.ts +1 -1
- package/dist/shims/error.js +2 -2
- package/dist/shims/fetch-cache.js +13 -4
- package/dist/shims/font-google-base.d.ts +11 -4
- package/dist/shims/font-google-base.js +17 -8
- package/dist/shims/font-local.d.ts +10 -3
- package/dist/shims/font-local.js +41 -10
- package/dist/shims/head.d.ts +13 -2
- package/dist/shims/head.js +3 -3
- package/dist/shims/headers.d.ts +37 -43
- package/dist/shims/headers.js +183 -74
- package/dist/shims/image.d.ts +27 -37
- package/dist/shims/image.js +21 -14
- package/dist/shims/internal/cookie-serialize.d.ts +12 -9
- package/dist/shims/internal/cookie-serialize.js +10 -7
- package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
- package/dist/shims/internal/interpolate-as.d.ts +15 -1
- package/dist/shims/internal/interpolate-as.js +27 -2
- package/dist/shims/internal/utils.d.ts +3 -3
- package/dist/shims/legacy-image.d.ts +3 -37
- package/dist/shims/legacy-image.js +6 -16
- package/dist/shims/link.d.ts +15 -22
- package/dist/shims/link.js +34 -13
- package/dist/shims/metadata.d.ts +7 -17
- package/dist/shims/metadata.js +74 -24
- package/dist/shims/navigation-context-state.d.ts +1 -1
- package/dist/shims/navigation.d.ts +7 -3
- package/dist/shims/navigation.js +25 -14
- package/dist/shims/navigation.react-server.js +1 -1
- package/dist/shims/next-shims-augmentations.d.ts +1 -0
- package/dist/shims/next-shims-public.d.ts +1 -0
- package/dist/shims/public-shim-map.json.js +103 -0
- package/dist/shims/readonly-url-search-params.d.ts +3 -3
- package/dist/shims/readonly-url-search-params.js +3 -3
- package/dist/shims/request-context.d.ts +4 -1
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/router.d.ts +55 -21
- package/dist/shims/router.js +180 -44
- package/dist/shims/script.d.ts +6 -10
- package/dist/shims/script.js +7 -4
- package/dist/shims/server.d.ts +50 -26
- package/dist/shims/server.js +193 -55
- package/dist/shims/unified-request-context.d.ts +22 -3
- package/dist/shims/unified-request-context.js +84 -1
- package/dist/shims/url-safety.d.ts +1 -1
- package/dist/shims/url-safety.js +2 -2
- package/dist/typegen.d.ts +8 -2
- package/dist/typegen.js +76 -15
- package/dist/utils/cache-control-metadata.d.ts +2 -1
- package/dist/utils/cache-control-metadata.js +5 -1
- package/dist/utils/domain-locale.d.ts +2 -2
- package/dist/utils/external-url.d.ts +5 -0
- package/dist/utils/external-url.js +7 -0
- package/dist/utils/html-limited-bots.js +1 -1
- package/dist/utils/protocol-headers.d.ts +7 -1
- package/dist/utils/protocol-headers.js +7 -1
- package/dist/utils/regex-safety.d.ts +8 -0
- package/dist/utils/regex-safety.js +737 -0
- package/package.json +13 -2
package/dist/shims/server.d.ts
CHANGED
|
@@ -9,28 +9,36 @@
|
|
|
9
9
|
* This is a pragmatic subset — we implement the most commonly used APIs
|
|
10
10
|
* rather than bug-for-bug parity with Next.js internals.
|
|
11
11
|
*/
|
|
12
|
+
/** @deprecated Import ImageResponse from `next/og` instead. */
|
|
13
|
+
declare function ImageResponse(): never;
|
|
14
|
+
type RequestInit = globalThis.RequestInit & {
|
|
15
|
+
nextConfig?: {
|
|
16
|
+
basePath?: string;
|
|
17
|
+
i18n?: {
|
|
18
|
+
locales: readonly string[];
|
|
19
|
+
defaultLocale: string;
|
|
20
|
+
domains?: ReadonlyArray<{
|
|
21
|
+
domain: string;
|
|
22
|
+
defaultLocale: string;
|
|
23
|
+
locales?: readonly string[];
|
|
24
|
+
http?: true;
|
|
25
|
+
}>;
|
|
26
|
+
} | null;
|
|
27
|
+
trailingSlash?: boolean;
|
|
28
|
+
};
|
|
29
|
+
signal?: AbortSignal;
|
|
30
|
+
duplex?: "half";
|
|
31
|
+
};
|
|
12
32
|
declare class NextRequest extends Request {
|
|
13
33
|
private _nextUrl;
|
|
14
34
|
private _url;
|
|
15
35
|
private _cookies;
|
|
16
|
-
constructor(input: URL | RequestInfo, init?: RequestInit
|
|
17
|
-
nextConfig?: {
|
|
18
|
-
basePath?: string;
|
|
19
|
-
i18n?: {
|
|
20
|
-
locales: string[];
|
|
21
|
-
defaultLocale: string;
|
|
22
|
-
domains?: Array<{
|
|
23
|
-
domain: string;
|
|
24
|
-
defaultLocale: string;
|
|
25
|
-
locales?: string[];
|
|
26
|
-
}>;
|
|
27
|
-
};
|
|
28
|
-
trailingSlash?: boolean;
|
|
29
|
-
};
|
|
30
|
-
});
|
|
36
|
+
constructor(input: URL | RequestInfo, init?: RequestInit);
|
|
31
37
|
get nextUrl(): NextURL;
|
|
32
38
|
get url(): string;
|
|
33
39
|
get cookies(): RequestCookies;
|
|
40
|
+
get page(): void;
|
|
41
|
+
get ua(): void;
|
|
34
42
|
/**
|
|
35
43
|
* Client IP address. Prefers Cloudflare's trusted CF-Connecting-IP header
|
|
36
44
|
* over the spoofable X-Forwarded-For. Returns undefined if unavailable.
|
|
@@ -65,12 +73,16 @@ declare class NextResponse<_Body = unknown> extends Response {
|
|
|
65
73
|
/**
|
|
66
74
|
* Create a redirect response.
|
|
67
75
|
*/
|
|
68
|
-
static redirect(url: string | URL |
|
|
76
|
+
static redirect(url: string | URL | {
|
|
77
|
+
toString(): string;
|
|
78
|
+
}, init?: number | ResponseInit): NextResponse;
|
|
69
79
|
/**
|
|
70
80
|
* Create a rewrite response (middleware pattern).
|
|
71
81
|
* Sets the x-middleware-rewrite header.
|
|
72
82
|
*/
|
|
73
|
-
static rewrite(destination: string | URL |
|
|
83
|
+
static rewrite(destination: string | URL | {
|
|
84
|
+
toString(): string;
|
|
85
|
+
}, init?: MiddlewareResponseInit): NextResponse;
|
|
74
86
|
/**
|
|
75
87
|
* Continue to the next handler (middleware pattern).
|
|
76
88
|
* Sets the x-middleware-next header.
|
|
@@ -176,6 +188,7 @@ declare class NextURL {
|
|
|
176
188
|
get locales(): string[] | undefined;
|
|
177
189
|
clone(): NextURL;
|
|
178
190
|
toString(): string;
|
|
191
|
+
toJSON(): string;
|
|
179
192
|
/**
|
|
180
193
|
* The build ID of the Next.js application.
|
|
181
194
|
* Set from `generateBuildId` in next.config.js, or a random UUID if not configured.
|
|
@@ -202,7 +215,7 @@ declare class RequestCookies {
|
|
|
202
215
|
toString(): string;
|
|
203
216
|
private _serialize;
|
|
204
217
|
private _syncHeader;
|
|
205
|
-
[Symbol.iterator]():
|
|
218
|
+
[Symbol.iterator](): MapIterator<[string, CookieEntry]>;
|
|
206
219
|
}
|
|
207
220
|
declare function sealRequestHeaders(headers: Headers): Headers;
|
|
208
221
|
declare function sealRequestCookies(cookies: RequestCookies): RequestCookies;
|
|
@@ -217,15 +230,16 @@ declare class ResponseCookies {
|
|
|
217
230
|
}]): this;
|
|
218
231
|
get(...args: [name: string] | [options: {
|
|
219
232
|
name: string;
|
|
220
|
-
}]):
|
|
233
|
+
}]): ResponseCookieEntry | undefined;
|
|
221
234
|
has(name: string): boolean;
|
|
222
235
|
getAll(...args: [name: string] | [options: {
|
|
223
236
|
name: string;
|
|
224
|
-
}] | []):
|
|
237
|
+
}] | []): ResponseCookieEntry[];
|
|
225
238
|
delete(...args: [name: string] | [options: Omit<CookieOptions & {
|
|
226
239
|
name: string;
|
|
227
240
|
}, "maxAge" | "expires">]): this;
|
|
228
|
-
[Symbol.iterator]():
|
|
241
|
+
[Symbol.iterator](): MapIterator<[string, ResponseCookieEntry]>;
|
|
242
|
+
toString(): string;
|
|
229
243
|
/** Delete all Set-Cookie headers and re-append from the internal map. */
|
|
230
244
|
private _syncHeaders;
|
|
231
245
|
}
|
|
@@ -233,11 +247,14 @@ type CookieOptions = {
|
|
|
233
247
|
path?: string;
|
|
234
248
|
domain?: string;
|
|
235
249
|
maxAge?: number;
|
|
236
|
-
expires?: Date;
|
|
250
|
+
expires?: Date | number;
|
|
237
251
|
httpOnly?: boolean;
|
|
238
252
|
secure?: boolean;
|
|
239
|
-
sameSite?: "
|
|
253
|
+
sameSite?: true | false | "strict" | "lax" | "none";
|
|
254
|
+
partitioned?: boolean;
|
|
255
|
+
priority?: "low" | "medium" | "high";
|
|
240
256
|
};
|
|
257
|
+
type ResponseCookieEntry = CookieEntry & CookieOptions;
|
|
241
258
|
type MiddlewareResponseInit = {
|
|
242
259
|
request?: {
|
|
243
260
|
headers?: Headers;
|
|
@@ -253,8 +270,16 @@ declare class NextFetchEvent {
|
|
|
253
270
|
sourcePage: string;
|
|
254
271
|
private _waitUntilPromises;
|
|
255
272
|
constructor(params: {
|
|
273
|
+
request?: Request;
|
|
256
274
|
page: string;
|
|
275
|
+
context?: {
|
|
276
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
277
|
+
};
|
|
257
278
|
});
|
|
279
|
+
private _externalWaitUntil?;
|
|
280
|
+
get request(): void;
|
|
281
|
+
respondWith(): void;
|
|
282
|
+
passThroughOnException(): void;
|
|
258
283
|
waitUntil(promise: Promise<unknown>): void;
|
|
259
284
|
get waitUntilPromises(): Promise<unknown>[];
|
|
260
285
|
/** Drain all waitUntil promises. Returns a single promise that settles when all are done. */
|
|
@@ -300,8 +325,7 @@ type UserAgent = {
|
|
|
300
325
|
*
|
|
301
326
|
* Uses the platform's `waitUntil` (via the per-request ExecutionContext) when
|
|
302
327
|
* available so the task survives past the response on Cloudflare Workers.
|
|
303
|
-
*
|
|
304
|
-
* context (e.g. Node.js dev server).
|
|
328
|
+
* Node.js dev drains callbacks from its response finish/close lifecycle.
|
|
305
329
|
*
|
|
306
330
|
* Throws when called inside a cached scope — request-specific
|
|
307
331
|
* side-effects must not leak into cached results.
|
|
@@ -320,4 +344,4 @@ declare function connection(): Promise<void>;
|
|
|
320
344
|
*/
|
|
321
345
|
declare const URLPattern: typeof globalThis.URLPattern;
|
|
322
346
|
//#endregion
|
|
323
|
-
export { MiddlewareResponseInit, NextFetchEvent, NextMiddleware, NextMiddlewareResult, NextRequest, NextResponse, NextURL, NextURLConfig, RequestCookies, ResponseCookies, URLPattern, UserAgent, after, connection, sealRequestCookies, sealRequestHeaders, userAgent, userAgentFromString };
|
|
347
|
+
export { ImageResponse, MiddlewareResponseInit, NextFetchEvent, NextMiddleware, NextMiddlewareResult, NextRequest, NextResponse, NextURL, NextURLConfig, RequestCookies, RequestInit, ResponseCookies, URLPattern, UserAgent, after, connection, sealRequestCookies, sealRequestHeaders, userAgent, userAgentFromString };
|
package/dist/shims/server.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { bindRequestContextSnapshot, getRequestContext, isInsideUnifiedScope, queueAfterCallback } from "./unified-request-context.js";
|
|
1
2
|
import { hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
2
3
|
import { getRequestExecutionContext } from "./request-context.js";
|
|
3
4
|
import { MIDDLEWARE_SET_COOKIE_HEADER } from "../utils/protocol-headers.js";
|
|
4
5
|
import { MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER } from "../server/headers.js";
|
|
5
6
|
import { encodeMiddlewareRequestHeaders } from "../utils/middleware-request-headers.js";
|
|
6
|
-
import {
|
|
7
|
+
import { validateCookieAttributeValue, validateCookieName } from "./internal/cookie-serialize.js";
|
|
7
8
|
import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
|
|
8
9
|
import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
9
10
|
//#region src/shims/server.ts
|
|
@@ -17,6 +18,10 @@ import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
|
17
18
|
* This is a pragmatic subset — we implement the most commonly used APIs
|
|
18
19
|
* rather than bug-for-bug parity with Next.js internals.
|
|
19
20
|
*/
|
|
21
|
+
/** @deprecated Import ImageResponse from `next/og` instead. */
|
|
22
|
+
function ImageResponse() {
|
|
23
|
+
throw new Error("ImageResponse has moved from next/server to next/og");
|
|
24
|
+
}
|
|
20
25
|
const _USE_CACHE_ALS_KEY = Symbol.for("vinext.cacheRuntime.contextAls");
|
|
21
26
|
const _UNSTABLE_CACHE_ALS_KEY = Symbol.for("vinext.unstableCache.als");
|
|
22
27
|
const _g = globalThis;
|
|
@@ -60,10 +65,18 @@ var NextRequest = class extends Request {
|
|
|
60
65
|
});
|
|
61
66
|
} else super(input, requestInit);
|
|
62
67
|
const url = typeof input === "string" ? new URL(input, "http://localhost") : input instanceof URL ? input : new URL(input.url, "http://localhost");
|
|
68
|
+
const i18n = _nextConfig?.i18n ? {
|
|
69
|
+
locales: [..._nextConfig.i18n.locales],
|
|
70
|
+
defaultLocale: _nextConfig.i18n.defaultLocale,
|
|
71
|
+
domains: _nextConfig.i18n.domains?.map((domain) => ({
|
|
72
|
+
...domain,
|
|
73
|
+
locales: domain.locales ? [...domain.locales] : void 0
|
|
74
|
+
}))
|
|
75
|
+
} : void 0;
|
|
63
76
|
const urlConfig = _nextConfig ? {
|
|
64
77
|
basePath: _nextConfig.basePath,
|
|
65
78
|
nextConfig: {
|
|
66
|
-
i18n
|
|
79
|
+
i18n,
|
|
67
80
|
trailingSlash: _nextConfig.trailingSlash
|
|
68
81
|
}
|
|
69
82
|
} : void 0;
|
|
@@ -80,6 +93,12 @@ var NextRequest = class extends Request {
|
|
|
80
93
|
get cookies() {
|
|
81
94
|
return this._cookies;
|
|
82
95
|
}
|
|
96
|
+
get page() {
|
|
97
|
+
throw new Error("NextRequest.page has been removed; use URLPattern instead");
|
|
98
|
+
}
|
|
99
|
+
get ua() {
|
|
100
|
+
throw new Error("NextRequest.ua has been removed; use userAgent() instead");
|
|
101
|
+
}
|
|
83
102
|
/**
|
|
84
103
|
* Client IP address. Prefers Cloudflare's trusted CF-Connecting-IP header
|
|
85
104
|
* over the spoofable X-Forwarded-For. Returns undefined if unavailable.
|
|
@@ -140,12 +159,8 @@ var NextResponse = class NextResponse extends Response {
|
|
|
140
159
|
* Create a JSON response.
|
|
141
160
|
*/
|
|
142
161
|
static json(body, init) {
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
return new NextResponse(JSON.stringify(body), {
|
|
146
|
-
...init,
|
|
147
|
-
headers
|
|
148
|
-
});
|
|
162
|
+
const response = Response.json(body, init);
|
|
163
|
+
return new NextResponse(response.body, response);
|
|
149
164
|
}
|
|
150
165
|
/**
|
|
151
166
|
* Create a redirect response.
|
|
@@ -399,7 +414,7 @@ var NextURL = class NextURL {
|
|
|
399
414
|
};
|
|
400
415
|
if (this._trailingSlash) nextConfig.trailingSlash = true;
|
|
401
416
|
const config = {
|
|
402
|
-
basePath: this.
|
|
417
|
+
basePath: this._configBasePath,
|
|
403
418
|
nextConfig: Object.keys(nextConfig).length > 0 ? nextConfig : void 0
|
|
404
419
|
};
|
|
405
420
|
return new NextURL(this.href, void 0, config);
|
|
@@ -407,6 +422,9 @@ var NextURL = class NextURL {
|
|
|
407
422
|
toString() {
|
|
408
423
|
return this.href;
|
|
409
424
|
}
|
|
425
|
+
toJSON() {
|
|
426
|
+
return this.href;
|
|
427
|
+
}
|
|
410
428
|
/**
|
|
411
429
|
* The build ID of the Next.js application.
|
|
412
430
|
* Set from `generateBuildId` in next.config.js, or a random UUID if not configured.
|
|
@@ -489,7 +507,7 @@ var RequestCookies = class {
|
|
|
489
507
|
else this._headers.set("cookie", this._serialize());
|
|
490
508
|
}
|
|
491
509
|
[Symbol.iterator]() {
|
|
492
|
-
return this.getAll().map((
|
|
510
|
+
return new Map(this.getAll().map((cookie) => [cookie.name, cookie])).entries();
|
|
493
511
|
}
|
|
494
512
|
};
|
|
495
513
|
var ReadonlyRequestCookiesError = class ReadonlyRequestCookiesError extends Error {
|
|
@@ -533,74 +551,54 @@ var ResponseCookies = class {
|
|
|
533
551
|
_parsed = /* @__PURE__ */ new Map();
|
|
534
552
|
constructor(headers) {
|
|
535
553
|
this._headers = headers;
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
const raw = header.slice(eq + 1, semi === -1 ? void 0 : semi);
|
|
542
|
-
let value;
|
|
543
|
-
try {
|
|
544
|
-
value = decodeURIComponent(raw);
|
|
545
|
-
} catch {
|
|
546
|
-
value = raw;
|
|
547
|
-
}
|
|
548
|
-
this._parsed.set(cookieName, {
|
|
549
|
-
serialized: header,
|
|
550
|
-
entry: {
|
|
551
|
-
name: cookieName,
|
|
552
|
-
value
|
|
553
|
-
}
|
|
554
|
-
});
|
|
554
|
+
const setCookie = headers.getSetCookie?.() ?? headers.get("set-cookie") ?? [];
|
|
555
|
+
const cookieStrings = Array.isArray(setCookie) ? setCookie : splitSetCookieString(setCookie);
|
|
556
|
+
for (const header of cookieStrings) {
|
|
557
|
+
const entry = parseSetCookieHeader(header);
|
|
558
|
+
if (entry) this._parsed.set(entry.name, entry);
|
|
555
559
|
}
|
|
556
560
|
}
|
|
557
561
|
set(...args) {
|
|
558
562
|
const [name, value, opts] = parseCookieSetArgs(args);
|
|
559
563
|
validateCookieName(name);
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
entry: {
|
|
564
|
-
name,
|
|
565
|
-
value
|
|
566
|
-
}
|
|
567
|
-
});
|
|
564
|
+
const entry = normalizeResponseCookie(name, value, opts);
|
|
565
|
+
validateResponseCookieAttributes(entry);
|
|
566
|
+
this._parsed.set(name, entry);
|
|
568
567
|
this._syncHeaders();
|
|
569
568
|
return this;
|
|
570
569
|
}
|
|
571
570
|
get(...args) {
|
|
572
571
|
const key = typeof args[0] === "string" ? args[0] : args[0].name;
|
|
573
|
-
return this._parsed.get(key)
|
|
572
|
+
return this._parsed.get(key);
|
|
574
573
|
}
|
|
575
574
|
has(name) {
|
|
576
575
|
return this._parsed.has(name);
|
|
577
576
|
}
|
|
578
577
|
getAll(...args) {
|
|
579
|
-
const all = [...this._parsed.values()]
|
|
578
|
+
const all = [...this._parsed.values()];
|
|
580
579
|
if (args.length === 0) return all;
|
|
581
580
|
const key = typeof args[0] === "string" ? args[0] : args[0].name;
|
|
582
581
|
return all.filter((c) => c.name === key);
|
|
583
582
|
}
|
|
584
583
|
delete(...args) {
|
|
585
|
-
const [name,
|
|
584
|
+
const [name, options] = typeof args[0] === "string" ? [args[0], void 0] : [args[0].name, args[0]];
|
|
586
585
|
return this.set({
|
|
586
|
+
...options,
|
|
587
587
|
name,
|
|
588
588
|
value: "",
|
|
589
|
-
expires: /* @__PURE__ */ new Date(0)
|
|
590
|
-
path: opts?.path,
|
|
591
|
-
domain: opts?.domain,
|
|
592
|
-
httpOnly: opts?.httpOnly,
|
|
593
|
-
secure: opts?.secure,
|
|
594
|
-
sameSite: opts?.sameSite
|
|
589
|
+
expires: /* @__PURE__ */ new Date(0)
|
|
595
590
|
});
|
|
596
591
|
}
|
|
597
592
|
[Symbol.iterator]() {
|
|
598
|
-
return [...this._parsed.values()].map((
|
|
593
|
+
return new Map([...this._parsed.values()].map((entry) => [entry.name, entry])).entries();
|
|
594
|
+
}
|
|
595
|
+
toString() {
|
|
596
|
+
return [...this._parsed.values()].map(stringifyResponseCookie).join("; ");
|
|
599
597
|
}
|
|
600
598
|
/** Delete all Set-Cookie headers and re-append from the internal map. */
|
|
601
599
|
_syncHeaders() {
|
|
602
600
|
this._headers.delete("Set-Cookie");
|
|
603
|
-
for (const
|
|
601
|
+
for (const entry of this._parsed.values()) this._headers.append("Set-Cookie", stringifyResponseCookie(entry));
|
|
604
602
|
}
|
|
605
603
|
};
|
|
606
604
|
var MiddlewareResponseCookies = class extends ResponseCookies {
|
|
@@ -628,6 +626,115 @@ var MiddlewareResponseCookies = class extends ResponseCookies {
|
|
|
628
626
|
this._responseHeaders.set(MIDDLEWARE_SET_COOKIE_HEADER, cookies.join(","));
|
|
629
627
|
}
|
|
630
628
|
};
|
|
629
|
+
function normalizeResponseCookie(name, value, options) {
|
|
630
|
+
const cookie = {
|
|
631
|
+
name,
|
|
632
|
+
value,
|
|
633
|
+
...options
|
|
634
|
+
};
|
|
635
|
+
if (typeof cookie.expires === "number") cookie.expires = new Date(cookie.expires);
|
|
636
|
+
if (cookie.maxAge) cookie.expires = new Date(Date.now() + cookie.maxAge * 1e3);
|
|
637
|
+
if (cookie.path == null) cookie.path = "/";
|
|
638
|
+
return cookie;
|
|
639
|
+
}
|
|
640
|
+
function parseSetCookieHeader(header) {
|
|
641
|
+
if (!header) return void 0;
|
|
642
|
+
const [[name, value], ...attributes] = parseResponseCookiePairs(header);
|
|
643
|
+
const { domain, expires, httponly, maxage, path, samesite, secure, partitioned, priority } = Object.fromEntries(attributes.map(([key, attributeValue]) => [key.toLowerCase().replaceAll("-", ""), attributeValue]));
|
|
644
|
+
return compactResponseCookie({
|
|
645
|
+
name,
|
|
646
|
+
value: decodeURIComponent(value),
|
|
647
|
+
domain,
|
|
648
|
+
...expires && { expires: new Date(expires) },
|
|
649
|
+
...httponly && { httpOnly: true },
|
|
650
|
+
...typeof maxage === "string" && { maxAge: Number(maxage) },
|
|
651
|
+
path,
|
|
652
|
+
...samesite && { sameSite: parseResponseCookieSameSite(samesite) },
|
|
653
|
+
...secure && { secure: true },
|
|
654
|
+
...priority && { priority: parseResponseCookiePriority(priority) },
|
|
655
|
+
...partitioned && { partitioned: true }
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
function parseResponseCookiePairs(cookie) {
|
|
659
|
+
const map = /* @__PURE__ */ new Map();
|
|
660
|
+
for (const pair of cookie.split(/; */)) {
|
|
661
|
+
if (!pair) continue;
|
|
662
|
+
const splitAt = pair.indexOf("=");
|
|
663
|
+
if (splitAt === -1) {
|
|
664
|
+
map.set(pair, "true");
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
const key = pair.slice(0, splitAt);
|
|
668
|
+
const value = pair.slice(splitAt + 1);
|
|
669
|
+
try {
|
|
670
|
+
map.set(key, decodeURIComponent(value ?? "true"));
|
|
671
|
+
} catch {}
|
|
672
|
+
}
|
|
673
|
+
return map;
|
|
674
|
+
}
|
|
675
|
+
function compactResponseCookie(cookie) {
|
|
676
|
+
const compact = {};
|
|
677
|
+
for (const key in cookie) if (cookie[key]) compact[key] = cookie[key];
|
|
678
|
+
return compact;
|
|
679
|
+
}
|
|
680
|
+
function parseResponseCookieSameSite(value) {
|
|
681
|
+
const sameSite = value.toLowerCase();
|
|
682
|
+
return sameSite === "strict" || sameSite === "lax" || sameSite === "none" ? sameSite : void 0;
|
|
683
|
+
}
|
|
684
|
+
function parseResponseCookiePriority(value) {
|
|
685
|
+
const priority = value.toLowerCase();
|
|
686
|
+
return priority === "low" || priority === "medium" || priority === "high" ? priority : void 0;
|
|
687
|
+
}
|
|
688
|
+
function validateResponseCookieAttributes(cookie) {
|
|
689
|
+
if (cookie.path) validateCookieAttributeValue(cookie.path, "Path");
|
|
690
|
+
if (cookie.domain) validateCookieAttributeValue(cookie.domain, "Domain");
|
|
691
|
+
}
|
|
692
|
+
function stringifyResponseCookie(cookie) {
|
|
693
|
+
const attributes = [
|
|
694
|
+
cookie.path && `Path=${cookie.path}`,
|
|
695
|
+
(cookie.expires || cookie.expires === 0) && `Expires=${(typeof cookie.expires === "number" ? new Date(cookie.expires) : cookie.expires).toUTCString()}`,
|
|
696
|
+
typeof cookie.maxAge === "number" && `Max-Age=${cookie.maxAge}`,
|
|
697
|
+
cookie.domain && `Domain=${cookie.domain}`,
|
|
698
|
+
cookie.secure && "Secure",
|
|
699
|
+
cookie.httpOnly && "HttpOnly",
|
|
700
|
+
cookie.sameSite && `SameSite=${cookie.sameSite}`,
|
|
701
|
+
cookie.partitioned && "Partitioned",
|
|
702
|
+
cookie.priority && `Priority=${cookie.priority}`
|
|
703
|
+
].filter(Boolean);
|
|
704
|
+
const stringified = `${cookie.name}=${encodeURIComponent(cookie.value ?? "")}`;
|
|
705
|
+
return attributes.length === 0 ? stringified : `${stringified}; ${attributes.join("; ")}`;
|
|
706
|
+
}
|
|
707
|
+
function splitSetCookieString(value) {
|
|
708
|
+
const cookies = [];
|
|
709
|
+
let position = 0;
|
|
710
|
+
let start = 0;
|
|
711
|
+
const skipWhitespace = () => {
|
|
712
|
+
while (position < value.length && /\s/.test(value.charAt(position))) position++;
|
|
713
|
+
return position < value.length;
|
|
714
|
+
};
|
|
715
|
+
while (position < value.length) {
|
|
716
|
+
start = position;
|
|
717
|
+
let separatorFound = false;
|
|
718
|
+
while (skipWhitespace()) {
|
|
719
|
+
if (value.charAt(position) !== ",") {
|
|
720
|
+
position++;
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
const lastComma = position++;
|
|
724
|
+
skipWhitespace();
|
|
725
|
+
const nextStart = position;
|
|
726
|
+
while (position < value.length && !"=;,".includes(value.charAt(position))) position++;
|
|
727
|
+
if (position < value.length && value.charAt(position) === "=") {
|
|
728
|
+
separatorFound = true;
|
|
729
|
+
position = nextStart;
|
|
730
|
+
cookies.push(value.substring(start, lastComma));
|
|
731
|
+
start = position;
|
|
732
|
+
} else position = lastComma + 1;
|
|
733
|
+
}
|
|
734
|
+
if (!separatorFound || position >= value.length) cookies.push(value.substring(start));
|
|
735
|
+
}
|
|
736
|
+
return cookies;
|
|
737
|
+
}
|
|
631
738
|
/**
|
|
632
739
|
* Parse the overloaded arguments for ResponseCookies.set():
|
|
633
740
|
* - (name, value, options?) — positional form
|
|
@@ -655,8 +762,21 @@ var NextFetchEvent = class {
|
|
|
655
762
|
_waitUntilPromises = [];
|
|
656
763
|
constructor(params) {
|
|
657
764
|
this.sourcePage = params.page;
|
|
765
|
+
if (params.context) this._externalWaitUntil = params.context.waitUntil.bind(params.context);
|
|
766
|
+
}
|
|
767
|
+
_externalWaitUntil;
|
|
768
|
+
get request() {
|
|
769
|
+
throw new Error(`The middleware signature for ${this.sourcePage} no longer exposes event.request`);
|
|
770
|
+
}
|
|
771
|
+
respondWith() {
|
|
772
|
+
throw new Error(`The middleware signature for ${this.sourcePage} no longer uses respondWith()`);
|
|
658
773
|
}
|
|
774
|
+
passThroughOnException() {}
|
|
659
775
|
waitUntil(promise) {
|
|
776
|
+
if (this._externalWaitUntil) {
|
|
777
|
+
this._externalWaitUntil(promise);
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
660
780
|
this._waitUntilPromises.push(promise);
|
|
661
781
|
}
|
|
662
782
|
get waitUntilPromises() {
|
|
@@ -691,18 +811,36 @@ function userAgent({ headers }) {
|
|
|
691
811
|
*
|
|
692
812
|
* Uses the platform's `waitUntil` (via the per-request ExecutionContext) when
|
|
693
813
|
* available so the task survives past the response on Cloudflare Workers.
|
|
694
|
-
*
|
|
695
|
-
* context (e.g. Node.js dev server).
|
|
814
|
+
* Node.js dev drains callbacks from its response finish/close lifecycle.
|
|
696
815
|
*
|
|
697
816
|
* Throws when called inside a cached scope — request-specific
|
|
698
817
|
* side-effects must not leak into cached results.
|
|
699
818
|
*/
|
|
700
819
|
function after(task) {
|
|
701
820
|
_throwIfInsideCacheScope("after()");
|
|
702
|
-
const
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
821
|
+
const requestContext = isInsideUnifiedScope() ? getRequestContext() : null;
|
|
822
|
+
if (!requestContext) {
|
|
823
|
+
const executionContext = getRequestExecutionContext();
|
|
824
|
+
if (executionContext) {
|
|
825
|
+
if (typeof task !== "function" && (task == null || typeof task.then !== "function")) throw new TypeError("`after()`: Argument must be a promise or a function");
|
|
826
|
+
const promise = typeof task === "function" ? Promise.resolve().then(task) : task;
|
|
827
|
+
const guarded = Promise.resolve(promise).catch((error) => {
|
|
828
|
+
console.error("[vinext] after() task failed:", error);
|
|
829
|
+
});
|
|
830
|
+
executionContext.waitUntil(guarded);
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
throw new Error("`after()` was called outside a request scope");
|
|
834
|
+
}
|
|
835
|
+
if (typeof task !== "function") {
|
|
836
|
+
if (task == null || typeof task.then !== "function") throw new TypeError("`after()`: Argument must be a promise or a function");
|
|
837
|
+
const guarded = Promise.resolve(task).catch((error) => {
|
|
838
|
+
console.error("[vinext] after() task failed:", error);
|
|
839
|
+
});
|
|
840
|
+
getRequestExecutionContext()?.waitUntil(guarded);
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
queueAfterCallback(requestContext, bindRequestContextSnapshot(requestContext, task));
|
|
706
844
|
}
|
|
707
845
|
/**
|
|
708
846
|
* connection() — signals that the response requires a live connection
|
|
@@ -727,4 +865,4 @@ const URLPattern = globalThis.URLPattern ?? (() => {
|
|
|
727
865
|
throw new Error("URLPattern is not available in this runtime. Install the `urlpattern-polyfill` package or upgrade to Node 20+.");
|
|
728
866
|
});
|
|
729
867
|
//#endregion
|
|
730
|
-
export { NextFetchEvent, NextRequest, NextResponse, NextURL, RequestCookies, ResponseCookies, URLPattern, after, connection, sealRequestCookies, sealRequestHeaders, userAgent, userAgentFromString };
|
|
868
|
+
export { ImageResponse, NextFetchEvent, NextRequest, NextResponse, NextURL, RequestCookies, ResponseCookies, URLPattern, after, connection, sealRequestCookies, sealRequestHeaders, userAgent, userAgentFromString };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { RootParamsState } from "./root-params.js";
|
|
2
1
|
import { CacheState } from "./cache-request-state.js";
|
|
2
|
+
import { RootParamsState } from "./root-params.js";
|
|
3
3
|
import { ExecutionContextLike } from "./request-context.js";
|
|
4
4
|
import { FetchCacheState } from "./fetch-cache.js";
|
|
5
5
|
import { VinextHeadersShimState } from "./headers.js";
|
|
@@ -18,13 +18,32 @@ import { NavigationState } from "./navigation-state.js";
|
|
|
18
18
|
*/
|
|
19
19
|
type UnifiedRequestContext = {
|
|
20
20
|
/** Cloudflare Workers ExecutionContext, or null on Node.js dev. */executionContext: ExecutionContextLike | null; /** Per-request cache for cacheForRequest(). Keyed by factory function reference. */
|
|
21
|
-
requestCache: WeakMap<(...args: any[]) => any, unknown>;
|
|
21
|
+
requestCache: WeakMap<(...args: any[]) => any, unknown>; /** Shared lifecycle state for work deferred until the response closes. */
|
|
22
|
+
afterContext: AfterRequestContext;
|
|
22
23
|
} & VinextHeadersShimState & I18nState & NavigationState & CacheState & PrivateCacheState & FetchCacheState & RouterState & HeadState & RootParamsState;
|
|
24
|
+
type AfterRequestContext = {
|
|
25
|
+
callbacks: Array<() => unknown>;
|
|
26
|
+
responseClosed: boolean;
|
|
27
|
+
pendingCallbacks: number;
|
|
28
|
+
completion: Promise<void> | null;
|
|
29
|
+
resolveCompletion: (() => void) | null;
|
|
30
|
+
};
|
|
23
31
|
/**
|
|
24
32
|
* Create a fresh `UnifiedRequestContext` with defaults for all fields.
|
|
25
33
|
* Pass partial overrides for the fields you need to pre-populate.
|
|
26
34
|
*/
|
|
27
35
|
declare function createRequestContext(opts?: Partial<UnifiedRequestContext>): UnifiedRequestContext;
|
|
36
|
+
/** Queue a callback until response close, or start it immediately once closed. */
|
|
37
|
+
declare function queueAfterCallback(ctx: UnifiedRequestContext, callback: () => unknown): void;
|
|
38
|
+
/** Bind a callback to every AsyncLocalStorage context active at registration. */
|
|
39
|
+
declare function bindRequestContextSnapshot<T>(ctx: UnifiedRequestContext, callback: () => T): () => T;
|
|
40
|
+
/**
|
|
41
|
+
* Release function-form `after()` work once the response body has closed.
|
|
42
|
+
* All queued callbacks start together, matching Next.js' unbounded PromiseQueue.
|
|
43
|
+
*/
|
|
44
|
+
declare function closeAfterResponse(ctx: UnifiedRequestContext): Promise<void>;
|
|
45
|
+
/** Wrap a response so deferred callbacks start on stream completion or cancellation. */
|
|
46
|
+
declare function closeAfterResponseWithBody(response: Response, ctx: UnifiedRequestContext): Response;
|
|
28
47
|
/**
|
|
29
48
|
* Run `fn` within a unified request context scope.
|
|
30
49
|
* All shim modules will read/write their state from `ctx` for the
|
|
@@ -65,4 +84,4 @@ declare function getRequestContext(): UnifiedRequestContext;
|
|
|
65
84
|
*/
|
|
66
85
|
declare function isInsideUnifiedScope(): boolean;
|
|
67
86
|
//#endregion
|
|
68
|
-
export { UnifiedRequestContext, createRequestContext, getRequestContext, isInsideUnifiedScope, runWithRequestContext, runWithUnifiedStateMutation };
|
|
87
|
+
export { AfterRequestContext, UnifiedRequestContext, bindRequestContextSnapshot, closeAfterResponse, closeAfterResponseWithBody, createRequestContext, getRequestContext, isInsideUnifiedScope, queueAfterCallback, runWithRequestContext, runWithUnifiedStateMutation };
|
|
@@ -16,6 +16,8 @@ function createRequestContext(opts) {
|
|
|
16
16
|
return {
|
|
17
17
|
headersContext: null,
|
|
18
18
|
actionRevalidationKind: 0,
|
|
19
|
+
pendingRevalidatedTags: /* @__PURE__ */ new Set(),
|
|
20
|
+
pendingRevalidations: /* @__PURE__ */ new Set(),
|
|
19
21
|
dynamicUsageDetected: false,
|
|
20
22
|
renderRequestApiUsage: /* @__PURE__ */ new Set(),
|
|
21
23
|
connectionProbe: null,
|
|
@@ -41,6 +43,13 @@ function createRequestContext(opts) {
|
|
|
41
43
|
currentFetchDedupeEntries: /* @__PURE__ */ new Map(),
|
|
42
44
|
executionContext: _getInheritedExecutionContext(),
|
|
43
45
|
requestCache: /* @__PURE__ */ new WeakMap(),
|
|
46
|
+
afterContext: {
|
|
47
|
+
callbacks: [],
|
|
48
|
+
responseClosed: false,
|
|
49
|
+
pendingCallbacks: 0,
|
|
50
|
+
completion: null,
|
|
51
|
+
resolveCompletion: null
|
|
52
|
+
},
|
|
44
53
|
ssrContext: null,
|
|
45
54
|
ssrHeadChildren: [],
|
|
46
55
|
documentInitialHead: [],
|
|
@@ -48,6 +57,80 @@ function createRequestContext(opts) {
|
|
|
48
57
|
...opts
|
|
49
58
|
};
|
|
50
59
|
}
|
|
60
|
+
function ensureAfterCompletion(ctx) {
|
|
61
|
+
const state = ctx.afterContext;
|
|
62
|
+
if (state.resolveCompletion && state.completion) return;
|
|
63
|
+
let resolveCompletion;
|
|
64
|
+
const completion = new Promise((resolve) => {
|
|
65
|
+
resolveCompletion = resolve;
|
|
66
|
+
});
|
|
67
|
+
state.completion = completion;
|
|
68
|
+
state.resolveCompletion = resolveCompletion;
|
|
69
|
+
ctx.executionContext?.waitUntil(completion);
|
|
70
|
+
}
|
|
71
|
+
function finishAfterCallbacksIfIdle(ctx) {
|
|
72
|
+
const state = ctx.afterContext;
|
|
73
|
+
if (!state.responseClosed || state.pendingCallbacks !== 0 || state.callbacks.length !== 0 || !state.resolveCompletion) return;
|
|
74
|
+
const resolveCompletion = state.resolveCompletion;
|
|
75
|
+
state.resolveCompletion = null;
|
|
76
|
+
resolveCompletion();
|
|
77
|
+
}
|
|
78
|
+
function startAfterCallback(ctx, callback) {
|
|
79
|
+
const state = ctx.afterContext;
|
|
80
|
+
ensureAfterCompletion(ctx);
|
|
81
|
+
state.pendingCallbacks += 1;
|
|
82
|
+
Promise.resolve().then(callback).catch((error) => {
|
|
83
|
+
console.error("[vinext] after() task failed:", error);
|
|
84
|
+
}).finally(() => {
|
|
85
|
+
state.pendingCallbacks -= 1;
|
|
86
|
+
finishAfterCallbacksIfIdle(ctx);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** Queue a callback until response close, or start it immediately once closed. */
|
|
90
|
+
function queueAfterCallback(ctx, callback) {
|
|
91
|
+
ensureAfterCompletion(ctx);
|
|
92
|
+
if (ctx.afterContext.responseClosed) startAfterCallback(ctx, callback);
|
|
93
|
+
else ctx.afterContext.callbacks.push(callback);
|
|
94
|
+
}
|
|
95
|
+
/** Bind a callback to every AsyncLocalStorage context active at registration. */
|
|
96
|
+
function bindRequestContextSnapshot(ctx, callback) {
|
|
97
|
+
const constructor = _als.constructor;
|
|
98
|
+
try {
|
|
99
|
+
const runInSnapshot = constructor.snapshot?.();
|
|
100
|
+
if (runInSnapshot) return () => runInSnapshot(callback);
|
|
101
|
+
} catch {}
|
|
102
|
+
return () => _als.run(ctx, callback);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Release function-form `after()` work once the response body has closed.
|
|
106
|
+
* All queued callbacks start together, matching Next.js' unbounded PromiseQueue.
|
|
107
|
+
*/
|
|
108
|
+
async function closeAfterResponse(ctx) {
|
|
109
|
+
const state = ctx.afterContext;
|
|
110
|
+
if (!state.responseClosed) {
|
|
111
|
+
state.responseClosed = true;
|
|
112
|
+
const callbacks = state.callbacks.splice(0);
|
|
113
|
+
for (const callback of callbacks) startAfterCallback(ctx, callback);
|
|
114
|
+
finishAfterCallbacksIfIdle(ctx);
|
|
115
|
+
}
|
|
116
|
+
return state.completion ?? Promise.resolve();
|
|
117
|
+
}
|
|
118
|
+
/** Wrap a response so deferred callbacks start on stream completion or cancellation. */
|
|
119
|
+
function closeAfterResponseWithBody(response, ctx) {
|
|
120
|
+
if (!response.body) {
|
|
121
|
+
queueMicrotask(() => void closeAfterResponse(ctx));
|
|
122
|
+
return response;
|
|
123
|
+
}
|
|
124
|
+
const passthrough = new TransformStream();
|
|
125
|
+
response.body.pipeTo(passthrough.writable).then(() => void closeAfterResponse(ctx), () => void closeAfterResponse(ctx));
|
|
126
|
+
const wrapped = new Response(passthrough.readable, {
|
|
127
|
+
status: response.status,
|
|
128
|
+
statusText: response.statusText,
|
|
129
|
+
headers: response.headers
|
|
130
|
+
});
|
|
131
|
+
wrapped.__vinextStreamedHtmlResponse = response.__vinextStreamedHtmlResponse;
|
|
132
|
+
return wrapped;
|
|
133
|
+
}
|
|
51
134
|
function runWithRequestContext(ctx, fn) {
|
|
52
135
|
return _als.run(ctx, fn);
|
|
53
136
|
}
|
|
@@ -84,4 +167,4 @@ function isInsideUnifiedScope() {
|
|
|
84
167
|
return _als.getStore() != null;
|
|
85
168
|
}
|
|
86
169
|
//#endregion
|
|
87
|
-
export { createRequestContext, getRequestContext, isInsideUnifiedScope, runWithRequestContext, runWithUnifiedStateMutation };
|
|
170
|
+
export { bindRequestContextSnapshot, closeAfterResponse, closeAfterResponseWithBody, createRequestContext, getRequestContext, isInsideUnifiedScope, queueAfterCallback, runWithRequestContext, runWithUnifiedStateMutation };
|