vinext 0.1.1 → 0.1.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 +2 -5
- package/dist/build/client-build-config.d.ts +7 -1
- package/dist/build/client-build-config.js +9 -1
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +41 -12
- package/dist/build/run-prerender.d.ts +10 -2
- package/dist/build/run-prerender.js +15 -1
- package/dist/check.js +4 -3
- package/dist/client/app-nav-failure-handler.d.ts +8 -0
- package/dist/client/app-nav-failure-handler.js +44 -0
- package/dist/client/navigation-runtime.d.ts +3 -2
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/window-next.d.ts +8 -5
- package/dist/client/window-next.js +12 -1
- package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
- package/dist/config/config-matchers.d.ts +11 -4
- package/dist/config/config-matchers.js +88 -16
- package/dist/config/next-config.d.ts +59 -4
- package/dist/config/next-config.js +149 -48
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +189 -101
- package/dist/entries/app-browser-entry.d.ts +9 -3
- package/dist/entries/app-browser-entry.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +71 -6
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/app-ssr-entry.js +1 -1
- package/dist/entries/pages-client-entry.js +54 -9
- package/dist/entries/pages-server-entry.js +48 -11
- package/dist/index.d.ts +0 -2
- package/dist/index.js +285 -139
- package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
- package/dist/plugins/dynamic-preload-metadata.js +415 -0
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/og-assets.js +2 -2
- package/dist/plugins/optimize-imports.d.ts +10 -5
- package/dist/plugins/optimize-imports.js +27 -21
- package/dist/plugins/postcss.js +7 -7
- package/dist/plugins/sass.d.ts +53 -24
- package/dist/plugins/sass.js +249 -1
- package/dist/plugins/typeof-window.d.ts +14 -0
- package/dist/plugins/typeof-window.js +150 -0
- package/dist/plugins/wasm-module-import.d.ts +15 -0
- package/dist/plugins/wasm-module-import.js +50 -0
- package/dist/routing/app-route-graph.d.ts +25 -2
- package/dist/routing/app-route-graph.js +91 -22
- package/dist/routing/file-matcher.d.ts +10 -1
- package/dist/routing/file-matcher.js +23 -2
- package/dist/routing/pages-router.js +3 -3
- package/dist/routing/utils.d.ts +35 -6
- package/dist/routing/utils.js +59 -7
- package/dist/server/api-handler.d.ts +6 -1
- package/dist/server/api-handler.js +21 -15
- package/dist/server/app-browser-action-result.d.ts +19 -6
- package/dist/server/app-browser-action-result.js +19 -10
- package/dist/server/app-browser-entry.js +269 -297
- package/dist/server/app-browser-error.d.ts +10 -3
- package/dist/server/app-browser-error.js +47 -6
- package/dist/server/app-browser-history-controller.d.ts +104 -0
- package/dist/server/app-browser-history-controller.js +210 -0
- package/dist/server/app-browser-hydration.d.ts +2 -0
- package/dist/server/app-browser-hydration.js +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +7 -4
- package/dist/server/app-browser-navigation-controller.js +33 -9
- package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
- package/dist/server/app-browser-rsc-redirect.js +30 -8
- package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
- package/dist/server/app-browser-server-action-navigation.js +9 -0
- package/dist/server/app-browser-state.js +4 -7
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-elements-wire.d.ts +6 -1
- package/dist/server/app-elements-wire.js +14 -4
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-fallback-renderer.d.ts +3 -1
- package/dist/server/app-fallback-renderer.js +6 -2
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.js +24 -3
- package/dist/server/app-page-boundary-render.d.ts +3 -1
- package/dist/server/app-page-boundary-render.js +31 -16
- package/dist/server/app-page-cache-render.d.ts +53 -0
- package/dist/server/app-page-cache-render.js +91 -0
- package/dist/server/app-page-cache.d.ts +16 -2
- package/dist/server/app-page-cache.js +71 -8
- package/dist/server/app-page-dispatch.d.ts +34 -0
- package/dist/server/app-page-dispatch.js +167 -97
- package/dist/server/app-page-element-builder.d.ts +23 -2
- package/dist/server/app-page-element-builder.js +42 -10
- package/dist/server/app-page-execution.d.ts +7 -2
- package/dist/server/app-page-execution.js +53 -18
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +4 -0
- package/dist/server/app-page-render-observation.d.ts +3 -1
- package/dist/server/app-page-render-observation.js +17 -1
- package/dist/server/app-page-render.d.ts +13 -2
- package/dist/server/app-page-render.js +48 -17
- package/dist/server/app-page-request.d.ts +3 -0
- package/dist/server/app-page-request.js +5 -3
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +5 -1
- package/dist/server/app-page-route-wiring.js +21 -11
- package/dist/server/app-page-stream.d.ts +16 -9
- package/dist/server/app-page-stream.js +12 -9
- package/dist/server/app-pages-bridge.d.ts +18 -0
- package/dist/server/app-pages-bridge.js +22 -5
- package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
- package/dist/server/app-ppr-fallback-shell-render.js +26 -0
- package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
- package/dist/server/app-ppr-fallback-shell.js +8 -1
- package/dist/server/app-route-handler-dispatch.js +9 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -0
- package/dist/server/app-route-handler-response.js +11 -10
- package/dist/server/app-route-handler-runtime.js +12 -1
- package/dist/server/app-router-entry.js +5 -0
- package/dist/server/app-rsc-cache-busting.js +2 -0
- package/dist/server/app-rsc-handler.d.ts +25 -0
- package/dist/server/app-rsc-handler.js +153 -53
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +2 -0
- package/dist/server/app-segment-config.d.ts +9 -1
- package/dist/server/app-segment-config.js +12 -3
- package/dist/server/app-server-action-execution.d.ts +12 -0
- package/dist/server/app-server-action-execution.js +47 -15
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +81 -8
- package/dist/server/app-ssr-stream.js +9 -1
- package/dist/server/cache-control.js +4 -0
- package/dist/server/dev-lockfile.js +2 -1
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +287 -63
- package/dist/server/headers.d.ts +8 -1
- package/dist/server/headers.js +8 -1
- package/dist/server/hybrid-route-priority.d.ts +22 -0
- package/dist/server/hybrid-route-priority.js +33 -0
- package/dist/server/image-optimization.d.ts +18 -9
- package/dist/server/image-optimization.js +37 -23
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/implicit-tags.js +4 -1
- package/dist/server/instrumentation-runtime.d.ts +6 -0
- package/dist/server/instrumentation-runtime.js +8 -0
- package/dist/server/isr-decision.d.ts +79 -0
- package/dist/server/isr-decision.js +70 -0
- package/dist/server/metadata-route-response.js +5 -3
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +11 -7
- package/dist/server/middleware.js +1 -0
- package/dist/server/navigation-planner.d.ts +186 -22
- package/dist/server/navigation-planner.js +302 -0
- package/dist/server/navigation-trace.d.ts +18 -1
- package/dist/server/navigation-trace.js +18 -1
- package/dist/server/normalize-path.d.ts +0 -8
- package/dist/server/normalize-path.js +3 -1
- package/dist/server/otel-tracer-extension.d.ts +45 -0
- package/dist/server/otel-tracer-extension.js +89 -0
- package/dist/server/pages-api-route.d.ts +20 -3
- package/dist/server/pages-api-route.js +19 -3
- package/dist/server/pages-asset-tags.d.ts +16 -4
- package/dist/server/pages-asset-tags.js +22 -12
- package/dist/server/pages-data-route.d.ts +8 -1
- package/dist/server/pages-data-route.js +16 -3
- package/dist/server/pages-get-initial-props.d.ts +54 -4
- package/dist/server/pages-get-initial-props.js +43 -1
- package/dist/server/pages-node-compat.d.ts +3 -11
- package/dist/server/pages-node-compat.js +175 -122
- package/dist/server/pages-page-data.d.ts +39 -2
- package/dist/server/pages-page-data.js +261 -46
- package/dist/server/pages-page-handler.d.ts +5 -2
- package/dist/server/pages-page-handler.js +78 -25
- package/dist/server/pages-page-response.d.ts +47 -2
- package/dist/server/pages-page-response.js +73 -9
- package/dist/server/pages-readiness.d.ts +1 -1
- package/dist/server/pages-request-pipeline.d.ts +16 -1
- package/dist/server/pages-request-pipeline.js +96 -38
- package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
- package/dist/server/pregenerated-concrete-paths.js +2 -19
- package/dist/server/prerender-manifest.d.ts +33 -0
- package/dist/server/prerender-manifest.js +54 -0
- package/dist/server/prerender-route-params.d.ts +1 -2
- package/dist/server/prod-server.d.ts +39 -1
- package/dist/server/prod-server.js +107 -37
- package/dist/server/request-pipeline.d.ts +3 -15
- package/dist/server/request-pipeline.js +58 -47
- package/dist/server/rsc-stream-hints.d.ts +5 -1
- package/dist/server/rsc-stream-hints.js +6 -1
- package/dist/server/seed-cache.js +10 -18
- package/dist/shims/app-router-scroll-state.d.ts +3 -1
- package/dist/shims/app-router-scroll-state.js +14 -2
- package/dist/shims/app-router-scroll.d.ts +3 -0
- package/dist/shims/app-router-scroll.js +28 -18
- package/dist/shims/cache-runtime.js +12 -4
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -1
- package/dist/shims/cdn-cache.d.ts +5 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
- package/dist/shims/dynamic-preload-chunks.js +79 -0
- package/dist/shims/dynamic.d.ts +4 -0
- package/dist/shims/dynamic.js +4 -2
- package/dist/shims/error-boundary.d.ts +6 -4
- package/dist/shims/error-boundary.js +7 -0
- package/dist/shims/error.js +38 -11
- package/dist/shims/error.react-server.d.ts +9 -0
- package/dist/shims/error.react-server.js +6 -0
- package/dist/shims/fetch-cache.d.ts +11 -1
- package/dist/shims/fetch-cache.js +55 -20
- package/dist/shims/hash-scroll.js +6 -1
- package/dist/shims/head.js +6 -1
- package/dist/shims/headers.d.ts +16 -2
- package/dist/shims/headers.js +66 -5
- package/dist/shims/image-config.js +7 -1
- package/dist/shims/internal/als-registry.js +28 -1
- package/dist/shims/internal/app-route-detection.d.ts +6 -3
- package/dist/shims/internal/app-route-detection.js +18 -23
- package/dist/shims/internal/app-router-context.d.ts +5 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
- package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
- package/dist/shims/internal/navigation-untracked.d.ts +35 -0
- package/dist/shims/internal/navigation-untracked.js +55 -0
- package/dist/shims/internal/pages-data-target.d.ts +7 -2
- package/dist/shims/internal/pages-data-target.js +17 -8
- package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
- package/dist/shims/internal/pages-router-accessor.js +13 -0
- package/dist/shims/internal/router-context.d.ts +2 -1
- package/dist/shims/internal/router-context.js +3 -1
- package/dist/shims/link.js +12 -5
- package/dist/shims/metadata.d.ts +6 -2
- package/dist/shims/metadata.js +32 -14
- package/dist/shims/navigation.d.ts +14 -17
- package/dist/shims/navigation.js +93 -46
- package/dist/shims/ppr-fallback-shell.d.ts +5 -1
- package/dist/shims/ppr-fallback-shell.js +28 -7
- package/dist/shims/router.d.ts +13 -2
- package/dist/shims/router.js +434 -116
- package/dist/shims/script-nonce-context.d.ts +1 -1
- package/dist/shims/script-nonce-context.js +11 -3
- package/dist/shims/server.d.ts +33 -2
- package/dist/shims/server.js +75 -18
- package/dist/shims/slot.js +1 -1
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/typegen.js +1 -0
- package/dist/utils/built-asset-url.d.ts +4 -0
- package/dist/utils/built-asset-url.js +11 -0
- package/dist/utils/client-build-manifest.js +15 -5
- package/dist/utils/client-runtime-metadata.d.ts +45 -0
- package/dist/utils/client-runtime-metadata.js +63 -0
- package/dist/utils/commonjs-loader.d.ts +16 -0
- package/dist/utils/commonjs-loader.js +100 -0
- package/dist/utils/deployment-id.d.ts +8 -0
- package/dist/utils/deployment-id.js +22 -0
- package/dist/utils/hash.d.ts +17 -1
- package/dist/utils/hash.js +36 -1
- package/dist/utils/html-limited-bots.d.ts +18 -1
- package/dist/utils/html-limited-bots.js +23 -1
- package/dist/utils/lazy-chunks.d.ts +27 -1
- package/dist/utils/lazy-chunks.js +65 -1
- package/dist/utils/manifest-paths.d.ts +20 -2
- package/dist/utils/manifest-paths.js +38 -3
- package/dist/utils/parse-cookie.d.ts +13 -0
- package/dist/utils/parse-cookie.js +52 -0
- package/dist/utils/path.d.ts +8 -1
- package/dist/utils/path.js +13 -1
- package/package.json +2 -2
- package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
- package/dist/shims/internal/parse-cookie-header.js +0 -30
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getOrCreateAls } from "./internal/als-registry.js";
|
|
2
2
|
import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
|
|
3
3
|
import { getRequestExecutionContext } from "./request-context.js";
|
|
4
|
+
import { markDynamicUsage } from "./headers.js";
|
|
4
5
|
import { encodeCacheTags } from "../utils/encode-cache-tag.js";
|
|
5
6
|
import { getDataCacheHandler } from "./cache.js";
|
|
6
7
|
//#region src/shims/fetch-cache.ts
|
|
@@ -32,6 +33,7 @@ import { getDataCacheHandler } from "./cache.js";
|
|
|
32
33
|
const HEADER_BLOCKLIST = ["traceparent", "tracestate"];
|
|
33
34
|
const CACHE_KEY_PREFIX = "v3";
|
|
34
35
|
const MAX_CACHE_KEY_BODY_BYTES = 1024 * 1024;
|
|
36
|
+
const ONE_YEAR_SECONDS = 31536e3;
|
|
35
37
|
var BodyTooLargeForCacheKeyError = class extends Error {
|
|
36
38
|
constructor() {
|
|
37
39
|
super("Fetch body too large for cache key generation");
|
|
@@ -292,6 +294,7 @@ const _fallbackState = _g[_FALLBACK_KEY] ??= {
|
|
|
292
294
|
currentRequestTags: [],
|
|
293
295
|
currentFetchSoftTags: [],
|
|
294
296
|
currentFetchCacheMode: null,
|
|
297
|
+
currentForceDynamicFetchDefault: false,
|
|
295
298
|
dynamicFetchUrls: /* @__PURE__ */ new Set(),
|
|
296
299
|
isFetchDedupeActive: false,
|
|
297
300
|
currentFetchDedupeEntries: /* @__PURE__ */ new Map()
|
|
@@ -309,6 +312,7 @@ function _resetFallbackState(isFetchDedupeActive) {
|
|
|
309
312
|
_fallbackState.currentRequestTags = [];
|
|
310
313
|
_fallbackState.currentFetchSoftTags = [];
|
|
311
314
|
_fallbackState.currentFetchCacheMode = null;
|
|
315
|
+
_fallbackState.currentForceDynamicFetchDefault = false;
|
|
312
316
|
_fallbackState.dynamicFetchUrls = /* @__PURE__ */ new Set();
|
|
313
317
|
_fallbackState.isFetchDedupeActive = isFetchDedupeActive;
|
|
314
318
|
_fallbackState.currentFetchDedupeEntries = /* @__PURE__ */ new Map();
|
|
@@ -319,6 +323,10 @@ function getFetchObservationUrl(input) {
|
|
|
319
323
|
function recordDynamicFetchObservation(input) {
|
|
320
324
|
_getState().dynamicFetchUrls.add(getFetchObservationUrl(input));
|
|
321
325
|
}
|
|
326
|
+
function markUncachedFetchForPageOutput(input) {
|
|
327
|
+
recordDynamicFetchObservation(input);
|
|
328
|
+
markDynamicUsage();
|
|
329
|
+
}
|
|
322
330
|
function recordCacheableFetchObservation(input) {
|
|
323
331
|
_getState().cacheableFetchUrls.add(getFetchObservationUrl(input));
|
|
324
332
|
}
|
|
@@ -369,19 +377,36 @@ function addCollectedRequestTags(tags) {
|
|
|
369
377
|
function setCurrentFetchSoftTags(tags) {
|
|
370
378
|
_getState().currentFetchSoftTags = [...tags];
|
|
371
379
|
}
|
|
380
|
+
/**
|
|
381
|
+
* Read the path-derived soft tags for the current render.
|
|
382
|
+
*
|
|
383
|
+
* Used by the "use cache" runtime to pass soft tags to the cache handler
|
|
384
|
+
* so that `revalidatePath()` invalidates "use cache" entries during the
|
|
385
|
+
* affected route's next request, even when the entry carries no hard tags.
|
|
386
|
+
*/
|
|
387
|
+
function getCurrentFetchSoftTags() {
|
|
388
|
+
return _getState().currentFetchSoftTags;
|
|
389
|
+
}
|
|
372
390
|
function setCurrentFetchCacheMode(mode) {
|
|
373
391
|
_getState().currentFetchCacheMode = mode;
|
|
374
392
|
}
|
|
393
|
+
function setCurrentForceDynamicFetchDefault(enabled) {
|
|
394
|
+
_getState().currentForceDynamicFetchDefault = enabled;
|
|
395
|
+
}
|
|
375
396
|
function isNoStoreFetch(cacheDirective, nextOpts) {
|
|
376
|
-
return cacheDirective === "no-store" || cacheDirective === "no-cache" || nextOpts?.revalidate ===
|
|
397
|
+
return cacheDirective === "no-store" || cacheDirective === "no-cache" || nextOpts?.revalidate === 0;
|
|
377
398
|
}
|
|
378
399
|
function isCacheableFetch(cacheDirective, nextOpts) {
|
|
379
|
-
return cacheDirective === "force-cache" || typeof nextOpts?.revalidate === "number" && nextOpts.revalidate > 0;
|
|
400
|
+
return cacheDirective === "force-cache" || nextOpts?.revalidate === false || typeof nextOpts?.revalidate === "number" && nextOpts.revalidate > 0;
|
|
380
401
|
}
|
|
381
402
|
function hasExplicitRevalidateValue(nextOpts) {
|
|
382
403
|
return nextOpts?.revalidate !== void 0;
|
|
383
404
|
}
|
|
384
|
-
function
|
|
405
|
+
function isFalsyRevalidate(nextOpts) {
|
|
406
|
+
return !nextOpts?.revalidate;
|
|
407
|
+
}
|
|
408
|
+
function resolveSegmentCacheDirective(cacheDirective, nextOpts, mode, forceDynamicFetchDefault) {
|
|
409
|
+
if (forceDynamicFetchDefault && (!mode || mode === "auto") && (cacheDirective === void 0 || cacheDirective === "default") && isFalsyRevalidate(nextOpts)) return "no-store";
|
|
385
410
|
if (!mode || mode === "auto") return cacheDirective;
|
|
386
411
|
switch (mode) {
|
|
387
412
|
case "force-cache": return "force-cache";
|
|
@@ -447,6 +472,20 @@ function cloneDedupeResponse(response) {
|
|
|
447
472
|
const [body1, body2] = response.body.tee();
|
|
448
473
|
return [buildDedupeClone(body1, response), buildDedupeClone(body2, response)];
|
|
449
474
|
}
|
|
475
|
+
function buildCachedFetchResponse(data, input) {
|
|
476
|
+
const response = new Response(data.body, {
|
|
477
|
+
status: data.status ?? 200,
|
|
478
|
+
headers: data.headers
|
|
479
|
+
});
|
|
480
|
+
Object.defineProperty(response, "url", {
|
|
481
|
+
value: data.url ?? getFetchObservationUrl(input),
|
|
482
|
+
configurable: true,
|
|
483
|
+
enumerable: true,
|
|
484
|
+
writable: false
|
|
485
|
+
});
|
|
486
|
+
if (_responseBodyRegistry && response.body) _responseBodyRegistry.register(response, new WeakRef(response.body));
|
|
487
|
+
return response;
|
|
488
|
+
}
|
|
450
489
|
function dedupeFetch(input, init) {
|
|
451
490
|
const state = _getState();
|
|
452
491
|
if (!state.isFetchDedupeActive) return originalFetch(input, init);
|
|
@@ -497,25 +536,26 @@ function dedupeFetch(input, init) {
|
|
|
497
536
|
function createPatchedFetch() {
|
|
498
537
|
return async function patchedFetch(input, init) {
|
|
499
538
|
const nextOpts = init?.next;
|
|
500
|
-
const cacheDirective = resolveSegmentCacheDirective(getFetchCacheDirective(input, init), nextOpts, _getState().currentFetchCacheMode);
|
|
539
|
+
const cacheDirective = resolveSegmentCacheDirective(getFetchCacheDirective(input, init), nextOpts, _getState().currentFetchCacheMode, _getState().currentForceDynamicFetchDefault);
|
|
501
540
|
if (!nextOpts && !cacheDirective) {
|
|
502
541
|
recordDynamicFetchObservation(input);
|
|
503
542
|
return dedupeFetch(input, init);
|
|
504
543
|
}
|
|
505
|
-
if (cacheDirective === "no-store" || cacheDirective === "no-cache" || nextOpts?.revalidate ===
|
|
544
|
+
if (cacheDirective === "no-store" || cacheDirective === "no-cache" || nextOpts?.revalidate === 0) {
|
|
506
545
|
const cleanInit = stripNextFromInit(init, cacheDirective);
|
|
507
|
-
|
|
546
|
+
markUncachedFetchForPageOutput(input);
|
|
508
547
|
return dedupeFetch(input, cleanInit);
|
|
509
548
|
}
|
|
510
|
-
if (!(cacheDirective === "force-cache" || typeof nextOpts?.revalidate === "number" && nextOpts.revalidate > 0) && hasAuthHeaders(input, init)) {
|
|
549
|
+
if (!(cacheDirective === "force-cache" || nextOpts?.revalidate === false || typeof nextOpts?.revalidate === "number" && nextOpts.revalidate > 0) && hasAuthHeaders(input, init)) {
|
|
511
550
|
const cleanInit = stripNextFromInit(init, cacheDirective);
|
|
512
551
|
recordDynamicFetchObservation(input);
|
|
513
552
|
return dedupeFetch(input, cleanInit);
|
|
514
553
|
}
|
|
515
554
|
let revalidateSeconds;
|
|
516
|
-
if (cacheDirective === "force-cache") revalidateSeconds = nextOpts?.revalidate && typeof nextOpts.revalidate === "number" ? nextOpts.revalidate :
|
|
555
|
+
if (cacheDirective === "force-cache") revalidateSeconds = nextOpts?.revalidate && typeof nextOpts.revalidate === "number" ? nextOpts.revalidate : ONE_YEAR_SECONDS;
|
|
556
|
+
else if (nextOpts?.revalidate === false) revalidateSeconds = ONE_YEAR_SECONDS;
|
|
517
557
|
else if (typeof nextOpts?.revalidate === "number" && nextOpts.revalidate > 0) revalidateSeconds = nextOpts.revalidate;
|
|
518
|
-
else if (nextOpts?.tags && nextOpts.tags.length > 0) revalidateSeconds =
|
|
558
|
+
else if (nextOpts?.tags && nextOpts.tags.length > 0) revalidateSeconds = ONE_YEAR_SECONDS;
|
|
519
559
|
else {
|
|
520
560
|
const cleanInit = stripNextFromInit(init, cacheDirective);
|
|
521
561
|
recordDynamicFetchObservation(input);
|
|
@@ -550,10 +590,7 @@ function createPatchedFetch() {
|
|
|
550
590
|
});
|
|
551
591
|
if (cached?.value && cached.value.kind === "FETCH" && cached.cacheState !== "stale") {
|
|
552
592
|
const cachedData = cached.value.data;
|
|
553
|
-
return
|
|
554
|
-
status: cachedData.status ?? 200,
|
|
555
|
-
headers: cachedData.headers
|
|
556
|
-
});
|
|
593
|
+
return buildCachedFetchResponse(cachedData, input);
|
|
557
594
|
}
|
|
558
595
|
if (cached?.value && cached.value.kind === "FETCH" && cached.cacheState === "stale") {
|
|
559
596
|
const staleData = cached.value.data;
|
|
@@ -571,7 +608,7 @@ function createPatchedFetch() {
|
|
|
571
608
|
data: {
|
|
572
609
|
headers: freshHeaders,
|
|
573
610
|
body: freshBody,
|
|
574
|
-
url:
|
|
611
|
+
url: freshResp.url,
|
|
575
612
|
status: freshResp.status
|
|
576
613
|
},
|
|
577
614
|
tags,
|
|
@@ -595,10 +632,7 @@ function createPatchedFetch() {
|
|
|
595
632
|
}, DEDUP_TIMEOUT_MS);
|
|
596
633
|
getRequestExecutionContext()?.waitUntil(refetchPromise);
|
|
597
634
|
}
|
|
598
|
-
return
|
|
599
|
-
status: staleData.status ?? 200,
|
|
600
|
-
headers: staleData.headers
|
|
601
|
-
});
|
|
635
|
+
return buildCachedFetchResponse(staleData, input);
|
|
602
636
|
}
|
|
603
637
|
} catch (cacheErr) {
|
|
604
638
|
console.error("[vinext] fetch cache read error:", cacheErr);
|
|
@@ -617,7 +651,7 @@ function createPatchedFetch() {
|
|
|
617
651
|
data: {
|
|
618
652
|
headers,
|
|
619
653
|
body,
|
|
620
|
-
url:
|
|
654
|
+
url: response.url,
|
|
621
655
|
status: cloned.status
|
|
622
656
|
},
|
|
623
657
|
tags,
|
|
@@ -690,6 +724,7 @@ async function runWithFetchCache(fn) {
|
|
|
690
724
|
currentRequestTags: [],
|
|
691
725
|
currentFetchSoftTags: [],
|
|
692
726
|
currentFetchCacheMode: null,
|
|
727
|
+
currentForceDynamicFetchDefault: false,
|
|
693
728
|
dynamicFetchUrls: /* @__PURE__ */ new Set(),
|
|
694
729
|
isFetchDedupeActive: true,
|
|
695
730
|
currentFetchDedupeEntries: /* @__PURE__ */ new Map()
|
|
@@ -728,4 +763,4 @@ function getOriginalFetch() {
|
|
|
728
763
|
return originalFetch;
|
|
729
764
|
}
|
|
730
765
|
//#endregion
|
|
731
|
-
export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getOriginalFetch, peekCacheableFetchObservations, peekDynamicFetchObservations, runWithFetchCache, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchSoftTags, withFetchCache };
|
|
766
|
+
export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getCurrentFetchSoftTags, getOriginalFetch, peekCacheableFetchObservations, peekDynamicFetchObservations, runWithFetchCache, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, withFetchCache };
|
|
@@ -17,7 +17,12 @@ function scrollToHashTarget(hash) {
|
|
|
17
17
|
idElement.scrollIntoView({ behavior: "auto" });
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
-
document.getElementsByName(fragment)[0]
|
|
20
|
+
const namedElement = document.getElementsByName(fragment)[0];
|
|
21
|
+
if (namedElement) {
|
|
22
|
+
namedElement.scrollIntoView({ behavior: "auto" });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
window.scrollTo(0, 0);
|
|
21
26
|
}
|
|
22
27
|
function scrollToHashTargetOnNextFrame(hash) {
|
|
23
28
|
requestAnimationFrame(() => {
|
package/dist/shims/head.js
CHANGED
|
@@ -104,6 +104,10 @@ const SELF_CLOSING_HEAD_TAGS = new Set([
|
|
|
104
104
|
]);
|
|
105
105
|
/** Tags whose content is raw text — closing-tag sequences must be escaped during SSR. */
|
|
106
106
|
const RAW_CONTENT_TAGS = new Set(["script", "style"]);
|
|
107
|
+
const INLINE_CLOSE_TAG_RES = {
|
|
108
|
+
script: /<\/(script)/gi,
|
|
109
|
+
style: /<\/(style)/gi
|
|
110
|
+
};
|
|
107
111
|
function warnDisallowedHeadTag(tag) {
|
|
108
112
|
if (process.env.NODE_ENV !== "production") console.warn(`[vinext] <Head> ignoring disallowed tag <${tag}>. Only ${ALLOWED_HEAD_TAGS_LIST} are allowed.`);
|
|
109
113
|
}
|
|
@@ -247,7 +251,8 @@ function escapeAttr(s) {
|
|
|
247
251
|
* context but prevents the HTML parser from seeing a closing tag.
|
|
248
252
|
*/
|
|
249
253
|
function escapeInlineContent(content, tag) {
|
|
250
|
-
const pattern =
|
|
254
|
+
const pattern = INLINE_CLOSE_TAG_RES[tag];
|
|
255
|
+
if (!pattern) return content;
|
|
251
256
|
return content.replace(pattern, "<\\/$1");
|
|
252
257
|
}
|
|
253
258
|
function getDangerouslySetInnerHTML(value) {
|
package/dist/shims/headers.d.ts
CHANGED
|
@@ -18,12 +18,24 @@ type HeadersAccessPhase = "render" | "action" | "route-handler";
|
|
|
18
18
|
type VinextHeadersShimState = {
|
|
19
19
|
headersContext: HeadersContext | null;
|
|
20
20
|
dynamicUsageDetected: boolean;
|
|
21
|
-
renderRequestApiUsage: Set<RenderRequestApiKind>;
|
|
21
|
+
renderRequestApiUsage: Set<RenderRequestApiKind>;
|
|
22
|
+
connectionProbe: ConnectionProbeState | null; /** Error recorded by throwIfInsideCacheScope for dev diagnostics, persists even if caught by user code. */
|
|
22
23
|
invalidDynamicUsageError: unknown;
|
|
23
24
|
pendingSetCookies: string[];
|
|
24
25
|
draftModeCookieHeader: string | null;
|
|
25
26
|
phase: HeadersAccessPhase;
|
|
26
27
|
};
|
|
28
|
+
type ConnectionProbeState = {
|
|
29
|
+
interrupted: boolean;
|
|
30
|
+
interrupt: () => void;
|
|
31
|
+
pending: Promise<never>;
|
|
32
|
+
};
|
|
33
|
+
type ConnectionProbeResult<T> = {
|
|
34
|
+
completed: true;
|
|
35
|
+
result: T;
|
|
36
|
+
} | {
|
|
37
|
+
completed: false;
|
|
38
|
+
};
|
|
27
39
|
/**
|
|
28
40
|
* Dynamic usage flag — set when a component calls connection(), cookies(),
|
|
29
41
|
* headers(), or noStore() during rendering. When true, ISR caching is
|
|
@@ -35,6 +47,8 @@ type VinextHeadersShimState = {
|
|
|
35
47
|
*/
|
|
36
48
|
declare function markDynamicUsage(): void;
|
|
37
49
|
declare function markRenderRequestApiUsage(kind: RenderRequestApiKind): void;
|
|
50
|
+
declare function runWithConnectionProbe<T>(fn: () => T | Promise<T>): Promise<ConnectionProbeResult<T>>;
|
|
51
|
+
declare function suspendConnectionProbe(): Promise<never> | null;
|
|
38
52
|
declare function peekRenderRequestApiUsage(): RenderRequestApiKind[];
|
|
39
53
|
declare function consumeRenderRequestApiUsage(): RenderRequestApiKind[];
|
|
40
54
|
/**
|
|
@@ -236,4 +250,4 @@ declare class RequestCookies {
|
|
|
236
250
|
toString(): string;
|
|
237
251
|
}
|
|
238
252
|
//#endregion
|
|
239
|
-
export { HeadersAccessPhase, HeadersContext, type RequestCookies, VinextHeadersShimState, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, throwIfInsideCacheScope };
|
|
253
|
+
export { HeadersAccessPhase, HeadersContext, type RequestCookies, VinextHeadersShimState, applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope };
|
package/dist/shims/headers.js
CHANGED
|
@@ -3,7 +3,8 @@ import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation }
|
|
|
3
3
|
import { MIDDLEWARE_SET_COOKIE_HEADER } from "../server/headers.js";
|
|
4
4
|
import { buildRequestHeadersFromMiddlewareResponse } from "../server/middleware-request-headers.js";
|
|
5
5
|
import { serializeSetCookie, validateCookieAttributeValue, validateCookieName } from "./internal/cookie-serialize.js";
|
|
6
|
-
import {
|
|
6
|
+
import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
|
|
7
|
+
import { createPprFallbackShellSuspensePromise } from "./ppr-fallback-shell.js";
|
|
7
8
|
//#region src/shims/headers.ts
|
|
8
9
|
/**
|
|
9
10
|
* next/headers shim
|
|
@@ -21,6 +22,7 @@ const _fallbackState = _g[_FALLBACK_KEY] ??= {
|
|
|
21
22
|
headersContext: null,
|
|
22
23
|
dynamicUsageDetected: false,
|
|
23
24
|
renderRequestApiUsage: /* @__PURE__ */ new Set(),
|
|
25
|
+
connectionProbe: null,
|
|
24
26
|
invalidDynamicUsageError: null,
|
|
25
27
|
pendingSetCookies: [],
|
|
26
28
|
draftModeCookieHeader: null,
|
|
@@ -80,7 +82,7 @@ function setCookieNameValue(setCookie) {
|
|
|
80
82
|
function rebuildCookiesFromHeader(ctx, cookieHeader) {
|
|
81
83
|
ctx.cookies.clear();
|
|
82
84
|
if (cookieHeader === null) return;
|
|
83
|
-
const nextCookies =
|
|
85
|
+
const nextCookies = parseEdgeRequestCookieHeader(cookieHeader);
|
|
84
86
|
for (const [name, value] of nextCookies) ctx.cookies.set(name, value);
|
|
85
87
|
}
|
|
86
88
|
function mergeMiddlewareSetCookies(ctx, rawHeader) {
|
|
@@ -115,6 +117,39 @@ function markDynamicUsage() {
|
|
|
115
117
|
function markRenderRequestApiUsage(kind) {
|
|
116
118
|
_getState().renderRequestApiUsage.add(kind);
|
|
117
119
|
}
|
|
120
|
+
async function runWithConnectionProbe(fn) {
|
|
121
|
+
const state = _getState();
|
|
122
|
+
const previousProbe = state.connectionProbe;
|
|
123
|
+
let interruptProbe = () => {};
|
|
124
|
+
const interrupted = new Promise((resolve) => {
|
|
125
|
+
interruptProbe = () => resolve({ completed: false });
|
|
126
|
+
});
|
|
127
|
+
const probe = {
|
|
128
|
+
interrupted: false,
|
|
129
|
+
interrupt() {
|
|
130
|
+
if (probe.interrupted) return;
|
|
131
|
+
probe.interrupted = true;
|
|
132
|
+
interruptProbe();
|
|
133
|
+
},
|
|
134
|
+
pending: new Promise(() => {})
|
|
135
|
+
};
|
|
136
|
+
state.connectionProbe = probe;
|
|
137
|
+
try {
|
|
138
|
+
const completed = Promise.resolve().then(fn).then((result) => ({
|
|
139
|
+
completed: true,
|
|
140
|
+
result
|
|
141
|
+
}));
|
|
142
|
+
return await Promise.race([completed, interrupted]);
|
|
143
|
+
} finally {
|
|
144
|
+
state.connectionProbe = previousProbe;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function suspendConnectionProbe() {
|
|
148
|
+
const probe = _getState().connectionProbe;
|
|
149
|
+
if (!probe) return null;
|
|
150
|
+
probe.interrupt();
|
|
151
|
+
return probe.pending;
|
|
152
|
+
}
|
|
118
153
|
function peekRenderRequestApiUsage() {
|
|
119
154
|
return [..._getState().renderRequestApiUsage].sort();
|
|
120
155
|
}
|
|
@@ -260,6 +295,7 @@ function runWithHeadersContext(ctx, fn) {
|
|
|
260
295
|
uCtx.headersContext = ctx;
|
|
261
296
|
uCtx.dynamicUsageDetected = false;
|
|
262
297
|
uCtx.renderRequestApiUsage = /* @__PURE__ */ new Set();
|
|
298
|
+
uCtx.connectionProbe = null;
|
|
263
299
|
uCtx.pendingSetCookies = [];
|
|
264
300
|
uCtx.draftModeCookieHeader = null;
|
|
265
301
|
uCtx.phase = "render";
|
|
@@ -268,6 +304,7 @@ function runWithHeadersContext(ctx, fn) {
|
|
|
268
304
|
headersContext: ctx,
|
|
269
305
|
dynamicUsageDetected: false,
|
|
270
306
|
renderRequestApiUsage: /* @__PURE__ */ new Set(),
|
|
307
|
+
connectionProbe: null,
|
|
271
308
|
invalidDynamicUsageError: null,
|
|
272
309
|
pendingSetCookies: [],
|
|
273
310
|
draftModeCookieHeader: null,
|
|
@@ -378,6 +415,26 @@ function _decorateRejectedRequestApiPromise(error) {
|
|
|
378
415
|
throw normalizedError;
|
|
379
416
|
} }));
|
|
380
417
|
}
|
|
418
|
+
function _decorateSuspendingRequestApiPromise(promise) {
|
|
419
|
+
return new Proxy(promise, {
|
|
420
|
+
get(promiseTarget, prop) {
|
|
421
|
+
if (prop === "then" || prop === "catch" || prop === "finally") {
|
|
422
|
+
const value = Reflect.get(promiseTarget, prop, promiseTarget);
|
|
423
|
+
return typeof value === "function" ? value.bind(promiseTarget) : value;
|
|
424
|
+
}
|
|
425
|
+
throw promise;
|
|
426
|
+
},
|
|
427
|
+
getOwnPropertyDescriptor() {
|
|
428
|
+
throw promise;
|
|
429
|
+
},
|
|
430
|
+
has() {
|
|
431
|
+
throw promise;
|
|
432
|
+
},
|
|
433
|
+
ownKeys() {
|
|
434
|
+
throw promise;
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
}
|
|
381
438
|
function _sealHeaders(headers) {
|
|
382
439
|
return new Proxy(headers, { get(target, prop) {
|
|
383
440
|
if (typeof prop === "string" && _HEADERS_MUTATING_METHODS.has(prop)) throw new ReadonlyHeadersError();
|
|
@@ -449,7 +506,7 @@ function headersContextFromRequest(request, options) {
|
|
|
449
506
|
let _cookies = null;
|
|
450
507
|
function getCookies() {
|
|
451
508
|
if (_cookies) return _cookies;
|
|
452
|
-
_cookies =
|
|
509
|
+
_cookies = parseEdgeRequestCookieHeader(headersProxy.get("cookie") || "");
|
|
453
510
|
return _cookies;
|
|
454
511
|
}
|
|
455
512
|
return {
|
|
@@ -476,6 +533,8 @@ function headers() {
|
|
|
476
533
|
if (!state.headersContext) return _decorateRejectedRequestApiPromise(/* @__PURE__ */ new Error("headers() can only be called from a Server Component, Route Handler, or Server Action. Make sure you're not calling it from a Client Component."));
|
|
477
534
|
if (state.headersContext.accessError) return _decorateRejectedRequestApiPromise(state.headersContext.accessError);
|
|
478
535
|
markDynamicUsage();
|
|
536
|
+
const fallbackShellPromise = createPprFallbackShellSuspensePromise("`headers()`");
|
|
537
|
+
if (fallbackShellPromise) return _decorateSuspendingRequestApiPromise(fallbackShellPromise);
|
|
479
538
|
return _getOrCreateDecoratedRequestApiPromise(_decoratedHeadersPromises, _getReadonlyHeaders(state.headersContext));
|
|
480
539
|
}
|
|
481
540
|
/**
|
|
@@ -493,6 +552,8 @@ function cookies() {
|
|
|
493
552
|
if (!state.headersContext) return _decorateRejectedRequestApiPromise(/* @__PURE__ */ new Error("cookies() can only be called from a Server Component, Route Handler, or Server Action."));
|
|
494
553
|
if (state.headersContext.accessError) return _decorateRejectedRequestApiPromise(state.headersContext.accessError);
|
|
495
554
|
markDynamicUsage();
|
|
555
|
+
const fallbackShellPromise = createPprFallbackShellSuspensePromise("`cookies()`");
|
|
556
|
+
if (fallbackShellPromise) return _decorateSuspendingRequestApiPromise(fallbackShellPromise);
|
|
496
557
|
return _getOrCreateDecoratedRequestApiPromise(_decoratedCookiesPromises, _areCookiesMutableInCurrentPhase() ? _getMutableCookies(state.headersContext) : _getReadonlyCookies(state.headersContext));
|
|
497
558
|
}
|
|
498
559
|
/** Accumulated Set-Cookie headers from cookies().set() / .delete() calls */
|
|
@@ -536,7 +597,7 @@ function ensureContextDraftModeSecret(ctx) {
|
|
|
536
597
|
function isDraftModeRequest(request, draftModeSecret) {
|
|
537
598
|
const cookieHeader = request.headers.get("cookie");
|
|
538
599
|
if (!cookieHeader) return false;
|
|
539
|
-
return
|
|
600
|
+
return parseEdgeRequestCookieHeader(cookieHeader).get(DRAFT_MODE_COOKIE) === validateDraftModeSecret(draftModeSecret);
|
|
540
601
|
}
|
|
541
602
|
function draftModeCookieAttributes() {
|
|
542
603
|
if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") return "Path=/; HttpOnly; SameSite=Lax";
|
|
@@ -690,4 +751,4 @@ var RequestCookies = class {
|
|
|
690
751
|
}
|
|
691
752
|
};
|
|
692
753
|
//#endregion
|
|
693
|
-
export { applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, throwIfInsideCacheScope };
|
|
754
|
+
export { applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import ipaddr from "ipaddr.js";
|
|
2
2
|
//#region src/shims/image-config.ts
|
|
3
|
+
const globRegexCache = /* @__PURE__ */ new Map();
|
|
3
4
|
/**
|
|
4
5
|
* Convert a glob pattern (with `*` and `**`) to a RegExp.
|
|
5
6
|
*
|
|
@@ -14,6 +15,9 @@ import ipaddr from "ipaddr.js";
|
|
|
14
15
|
* Literal characters are escaped for regex safety.
|
|
15
16
|
*/
|
|
16
17
|
function globToRegex(pattern, separator) {
|
|
18
|
+
const key = `${separator}\0${pattern}`;
|
|
19
|
+
const cached = globRegexCache.get(key);
|
|
20
|
+
if (cached !== void 0) return cached;
|
|
17
21
|
let regexStr = "^";
|
|
18
22
|
const doubleStar = separator === "." ? ".+" : ".*";
|
|
19
23
|
const singleStar = separator === "." ? "[^.]+" : "[^/]+";
|
|
@@ -27,7 +31,9 @@ function globToRegex(pattern, separator) {
|
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
regexStr += "$";
|
|
30
|
-
|
|
34
|
+
const re = new RegExp(regexStr);
|
|
35
|
+
globRegexCache.set(key, re);
|
|
36
|
+
return re;
|
|
31
37
|
}
|
|
32
38
|
/**
|
|
33
39
|
* Check whether a URL matches a single remote pattern.
|
|
@@ -38,6 +38,33 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
38
38
|
*/
|
|
39
39
|
const _g = globalThis;
|
|
40
40
|
/**
|
|
41
|
+
* No-op AsyncLocalStorage used when the runtime does not provide a usable
|
|
42
|
+
* `AsyncLocalStorage` constructor.
|
|
43
|
+
*
|
|
44
|
+
* In browser/client bundles `node:async_hooks` can resolve to a stub without a
|
|
45
|
+
* usable constructor (e.g. Vite's `__vite-browser-external`). Constructing such
|
|
46
|
+
* a value with `new` throws `TypeError: AsyncLocalStorage is not a constructor`
|
|
47
|
+
* at module-eval time, crashing every client-reachable shim that calls
|
|
48
|
+
* `getOrCreateAls` on import (request-context, headers, cache, …).
|
|
49
|
+
*
|
|
50
|
+
* Mirrors Next.js' `FakeAsyncLocalStorage` (and this repo's
|
|
51
|
+
* `async-hooks-stub.ts` client virtual module): `getStore()` returns
|
|
52
|
+
* `undefined` so shims fall back to their non-ALS code path, and the mutating
|
|
53
|
+
* methods are best-effort no-ops that still invoke the callback.
|
|
54
|
+
* See: https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/async-local-storage.ts
|
|
55
|
+
*/
|
|
56
|
+
var NoopAsyncLocalStorage = class {
|
|
57
|
+
getStore() {}
|
|
58
|
+
run(_store, fn, ...args) {
|
|
59
|
+
return fn(...args);
|
|
60
|
+
}
|
|
61
|
+
exit(fn, ...args) {
|
|
62
|
+
return fn(...args);
|
|
63
|
+
}
|
|
64
|
+
enterWith(_store) {}
|
|
65
|
+
disable() {}
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
41
68
|
* Get (or lazily create) the AsyncLocalStorage registered on `globalThis`
|
|
42
69
|
* under `Symbol.for(key)`. Multiple callers — including callers in different
|
|
43
70
|
* module instances — that pass the same `key` receive the same ALS instance.
|
|
@@ -47,7 +74,7 @@ const _g = globalThis;
|
|
|
47
74
|
*/
|
|
48
75
|
function getOrCreateAls(key) {
|
|
49
76
|
const sym = Symbol.for(key);
|
|
50
|
-
return _g[sym] ??= new AsyncLocalStorage();
|
|
77
|
+
return _g[sym] ??= typeof AsyncLocalStorage === "function" ? new AsyncLocalStorage() : new NoopAsyncLocalStorage();
|
|
51
78
|
}
|
|
52
79
|
//#endregion
|
|
53
80
|
export { getOrCreateAls };
|
|
@@ -27,9 +27,12 @@ declare function getPagesRouterComponentsMap(): PagesRouterComponentsMap;
|
|
|
27
27
|
* Pages Router map when the href matches an App Router route. No-op when the
|
|
28
28
|
* manifest is absent, the URL is external, or no app route matches.
|
|
29
29
|
*
|
|
30
|
-
* `pathname` is the basePath-stripped path —
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* `pathname` is the basePath-stripped, trailing-slash-stripped path —
|
|
31
|
+
* matching Next.js's `removeTrailingSlash(removeBasePath(pathname))` key used
|
|
32
|
+
* at read time (router.ts:1442). Stripping here ensures the write and read
|
|
33
|
+
* keys agree regardless of whether the caller normalised trailing slashes
|
|
34
|
+
* first (e.g. `link.tsx` normalises to match `trailingSlash` config before
|
|
35
|
+
* calling, while `router.prefetch()` passes the raw user-supplied URL).
|
|
33
36
|
*/
|
|
34
37
|
declare function markAppRouteDetectedOnPrefetch(href: string, basePath: string): void;
|
|
35
38
|
//#endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { stripBasePath } from "../../utils/base-path.js";
|
|
2
|
-
import {
|
|
1
|
+
import { removeTrailingSlash, stripBasePath } from "../../utils/base-path.js";
|
|
2
|
+
import { getLocalePathPrefix } from "../../utils/domain-locale.js";
|
|
3
|
+
import { resolveHybridClientRouteOwner } from "./hybrid-client-route-owner.js";
|
|
3
4
|
//#region src/shims/internal/app-route-detection.ts
|
|
4
|
-
const appRouteTrieCache = createRouteTrieCache();
|
|
5
5
|
const _COMPONENTS_KEY = Symbol.for("vinext.pagesRouter.components");
|
|
6
6
|
/**
|
|
7
7
|
* Get-or-create the Pages Router `components` map. Returns the same object
|
|
@@ -32,35 +32,30 @@ function resolveSameOriginPathname(href, basePath) {
|
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
34
|
if (url.origin !== window.location.origin) return null;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* absent (Pages-Router-only build), the URL is external, or no route matches.
|
|
41
|
-
*/
|
|
42
|
-
function matchesAppRoute(href, basePath) {
|
|
43
|
-
if (typeof window === "undefined") return false;
|
|
44
|
-
const routes = window.__VINEXT_LINK_PREFETCH_ROUTES__;
|
|
45
|
-
if (!routes || routes.length === 0) return false;
|
|
46
|
-
const pathname = resolveSameOriginPathname(href, basePath);
|
|
47
|
-
if (pathname === null) return false;
|
|
48
|
-
return matchRouteWithTrie(pathname, routes, appRouteTrieCache) !== null;
|
|
35
|
+
const pathname = stripBasePath(url.pathname, basePath);
|
|
36
|
+
const locale = getLocalePathPrefix(pathname, window.__VINEXT_LOCALES__);
|
|
37
|
+
if (!locale) return pathname;
|
|
38
|
+
const localePrefixLength = locale.length + 1;
|
|
39
|
+
return pathname.length === localePrefixLength ? "/" : pathname.slice(localePrefixLength);
|
|
49
40
|
}
|
|
50
41
|
/**
|
|
51
42
|
* Record `components[pathname] = { __appRouter: true }` on the shared
|
|
52
43
|
* Pages Router map when the href matches an App Router route. No-op when the
|
|
53
44
|
* manifest is absent, the URL is external, or no app route matches.
|
|
54
45
|
*
|
|
55
|
-
* `pathname` is the basePath-stripped path —
|
|
56
|
-
*
|
|
57
|
-
*
|
|
46
|
+
* `pathname` is the basePath-stripped, trailing-slash-stripped path —
|
|
47
|
+
* matching Next.js's `removeTrailingSlash(removeBasePath(pathname))` key used
|
|
48
|
+
* at read time (router.ts:1442). Stripping here ensures the write and read
|
|
49
|
+
* keys agree regardless of whether the caller normalised trailing slashes
|
|
50
|
+
* first (e.g. `link.tsx` normalises to match `trailingSlash` config before
|
|
51
|
+
* calling, while `router.prefetch()` passes the raw user-supplied URL).
|
|
58
52
|
*/
|
|
59
53
|
function markAppRouteDetectedOnPrefetch(href, basePath) {
|
|
60
54
|
if (typeof window === "undefined") return;
|
|
61
|
-
if (
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
55
|
+
if (resolveHybridClientRouteOwner(href, basePath) !== "app") return;
|
|
56
|
+
const rawPathname = resolveSameOriginPathname(href, basePath);
|
|
57
|
+
if (rawPathname === null) return;
|
|
58
|
+
const pathname = removeTrailingSlash(rawPathname);
|
|
64
59
|
getPagesRouterComponentsMap()[pathname] = { __appRouter: true };
|
|
65
60
|
}
|
|
66
61
|
//#endregion
|
|
@@ -16,6 +16,11 @@ type AppRouterInstance = {
|
|
|
16
16
|
push(href: string, options?: NavigateOptions): void;
|
|
17
17
|
replace(href: string, options?: NavigateOptions): void;
|
|
18
18
|
prefetch(href: string, options?: PrefetchOptions): void;
|
|
19
|
+
/**
|
|
20
|
+
* Perform an experimental gesture transition navigation.
|
|
21
|
+
* Only available when experimental.gestureTransition is enabled.
|
|
22
|
+
*/
|
|
23
|
+
experimental_gesturePush?(href: string, options?: NavigateOptions): void;
|
|
19
24
|
};
|
|
20
25
|
declare const AppRouterContext: React$1.Context<AppRouterInstance | null> | null;
|
|
21
26
|
declare const GlobalLayoutRouterContext: React$1.Context<unknown> | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NextRewrite } from "../../config/next-config.js";
|
|
2
|
+
import { VinextLinkPrefetchRoute, VinextPagesLinkPrefetchRoute } from "../../client/vinext-next-data.js";
|
|
3
|
+
|
|
4
|
+
//#region src/shims/internal/hybrid-client-route-owner.d.ts
|
|
5
|
+
type HybridClientOwner = "app" | "document" | "pages";
|
|
6
|
+
declare global {
|
|
7
|
+
interface Window {
|
|
8
|
+
__VINEXT_LINK_PREFETCH_ROUTES__?: VinextLinkPrefetchRoute[];
|
|
9
|
+
__VINEXT_PAGES_LINK_PREFETCH_ROUTES__?: VinextPagesLinkPrefetchRoute[];
|
|
10
|
+
__VINEXT_CLIENT_REWRITES__?: {
|
|
11
|
+
afterFiles: NextRewrite[];
|
|
12
|
+
beforeFiles: NextRewrite[];
|
|
13
|
+
fallback: NextRewrite[];
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Decide which router should own a soft-navigated URL. Returns:
|
|
19
|
+
* - "app" → the App Router runtime handles the navigation (RSC fetch).
|
|
20
|
+
* - "pages" → Pages owns the URL; the caller must hard-navigate instead.
|
|
21
|
+
* - null → no router matched (preserves the existing 404 path).
|
|
22
|
+
*
|
|
23
|
+
* `basePath` must match what the page uses (typically `process.env.__NEXT_ROUTER_BASEPATH`).
|
|
24
|
+
*
|
|
25
|
+
* The lookup uses the App and Pages manifests on `window` so the same
|
|
26
|
+
* matcher trie produces the same result the server will see when the
|
|
27
|
+
* request lands.
|
|
28
|
+
*/
|
|
29
|
+
declare function resolveHybridClientRouteOwner(href: string, basePath: string): HybridClientOwner | null;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { HybridClientOwner, resolveHybridClientRouteOwner };
|