@rangojs/router 0.26.6 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/rango.js +1 -1
- package/dist/types/__internal.d.ts +7 -1
- package/dist/types/browser/action-coordinator.d.ts +0 -4
- package/dist/types/browser/action-fence.d.ts +11 -3
- package/dist/types/browser/event-controller.d.ts +20 -1
- package/dist/types/browser/history-state.d.ts +7 -9
- package/dist/types/browser/intercept-utils.d.ts +23 -0
- package/dist/types/browser/navigation-store.d.ts +8 -6
- package/dist/types/browser/react/filter-segment-order.d.ts +2 -2
- package/dist/types/browser/rsc-router.d.ts +1 -1
- package/dist/types/browser/segment-reconciler.d.ts +6 -4
- package/dist/types/browser/types.d.ts +2 -1
- package/dist/types/browser/wire-protocol.d.ts +25 -0
- package/dist/types/cache/cache-key-utils.d.ts +11 -5
- package/dist/types/cache/cache-scope.d.ts +34 -22
- package/dist/types/cache/cf/cf-cache-constants.d.ts +2 -2
- package/dist/types/cache/cf/cf-cache-store.d.ts +47 -65
- package/dist/types/cache/cf/cf-kv-utils.d.ts +1 -1
- package/dist/types/cache/handle-snapshot.d.ts +9 -4
- package/dist/types/cache/segment-codec.d.ts +14 -0
- package/dist/types/cache/shell-snapshot.d.ts +1 -1
- package/dist/types/cache/tag-invalidation.d.ts +10 -0
- package/dist/types/cache/taint.d.ts +5 -3
- package/dist/types/cache/types.d.ts +7 -3
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +8 -6
- package/dist/types/prefetch-markers.d.ts +4 -6
- package/dist/types/prerender/store.d.ts +31 -0
- package/dist/types/prerender/warm-request.d.ts +3 -3
- package/dist/types/prerender.d.ts +2 -2
- package/dist/types/route-name.d.ts +5 -0
- package/dist/types/router/error-handling.d.ts +4 -4
- package/dist/types/router/instrument.d.ts +4 -3
- package/dist/types/router/intercept-resolution.d.ts +25 -9
- package/dist/types/router/match-context.d.ts +12 -11
- package/dist/types/router/match-handlers.d.ts +2 -6
- package/dist/types/router/match-middleware/background-revalidation.d.ts +10 -20
- package/dist/types/router/match-middleware/cache-lookup.d.ts +35 -87
- package/dist/types/router/match-middleware/cache-store.d.ts +2 -2
- package/dist/types/router/match-middleware/segment-resolution.d.ts +8 -6
- package/dist/types/router/prerender-match.d.ts +21 -6
- package/dist/types/router/preview-match.d.ts +2 -7
- package/dist/types/router/request-classification.d.ts +5 -0
- package/dist/types/router/revalidation.d.ts +6 -1
- package/dist/types/router/router-context.d.ts +9 -63
- package/dist/types/router/router-interfaces.d.ts +8 -14
- package/dist/types/router/segment-resolution/loader-cache.d.ts +3 -3
- package/dist/types/router/segment-resolution/loader-mask.d.ts +4 -4
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +20 -18
- package/dist/types/router/segment-resolution/resolution-pass.d.ts +93 -0
- package/dist/types/router/segment-resolution/revalidation.d.ts +82 -31
- package/dist/types/router/segment-resolution.d.ts +1 -2
- package/dist/types/router/segment-wrappers.d.ts +11 -48
- package/dist/types/router/telemetry.d.ts +2 -0
- package/dist/types/router/types.d.ts +10 -0
- package/dist/types/rsc/full-payload.d.ts +2 -2
- package/dist/types/rsc/handler-context.d.ts +6 -6
- package/dist/types/rsc/json-route-result.d.ts +5 -9
- package/dist/types/rsc/request-stages.d.ts +203 -0
- package/dist/types/rsc/response-cache-serve.d.ts +7 -12
- package/dist/types/rsc/response-route-handler.d.ts +2 -2
- package/dist/types/rsc/routine-plan.d.ts +1 -1
- package/dist/types/rsc/server-action.d.ts +2 -2
- package/dist/types/rsc/shell-capture-constants.d.ts +2 -2
- package/dist/types/rsc/shell-capture.d.ts +132 -15
- package/dist/types/rsc/shell-serve.d.ts +37 -12
- package/dist/types/server/context.d.ts +9 -8
- package/dist/types/server/handle-store.d.ts +16 -0
- package/dist/types/server/render-pass.d.ts +72 -0
- package/dist/types/server/request-context.d.ts +24 -104
- package/dist/types/server/rewrite-trail.d.ts +2 -2
- package/dist/types/testing/dispatch.d.ts +35 -18
- package/dist/types/testing/serve-shell-request.d.ts +7 -0
- package/dist/types/types/cache-types.d.ts +6 -3
- package/dist/types/types/error-types.d.ts +9 -1
- package/dist/types/types/handler-context.d.ts +18 -7
- package/dist/types/types/segments.d.ts +1 -1
- package/dist/types/vite/discovery/build-discovery-phase.d.ts +40 -0
- package/dist/types/vite/discovery/build-env.d.ts +22 -0
- package/dist/types/vite/discovery/bundle-scan-phase.d.ts +12 -0
- package/dist/types/vite/discovery/dev-prerender-cache.d.ts +3 -2
- package/dist/types/vite/discovery/dev-server-phase.d.ts +26 -0
- package/dist/types/vite/discovery/discovery-errors.d.ts +1 -1
- package/dist/types/vite/discovery/state.d.ts +12 -0
- package/dist/types/vite/plugins/version-plugin.d.ts +1 -1
- package/dist/types/vite/plugins/virtual-entries.d.ts +1 -1
- package/dist/types/vite/router-discovery.d.ts +8 -47
- package/dist/types/vite/temp-rsc-server.d.ts +39 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +9 -0
- package/dist/types/wire-params.d.ts +34 -0
- package/dist/vite/index.js +3809 -3710
- package/package.json +1 -1
- package/skills/cache-guide/SKILL.md +8 -5
- package/skills/caching/SKILL.md +37 -18
- package/skills/client-urls/SKILL.md +2 -1
- package/skills/document-cache/SKILL.md +18 -1
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/intercept/SKILL.md +53 -13
- package/skills/layout/SKILL.md +11 -7
- package/skills/loader/SKILL.md +30 -13
- package/skills/middleware/SKILL.md +19 -1
- package/skills/migrate-nextjs/SKILL.md +5 -4
- package/skills/parallel/SKILL.md +5 -4
- package/skills/ppr/SKILL.md +19 -3
- package/skills/prerender/SKILL.md +39 -15
- package/skills/rango/SKILL.md +23 -11
- package/skills/server-actions/SKILL.md +51 -6
- package/skills/testing/predicates.md +1 -1
- package/skills/testing/response-routes.md +6 -4
- package/skills/testing/serve-shell-request.md +7 -7
- package/skills/use-cache/SKILL.md +46 -8
- package/skills/ux-architecture/SKILL.md +3 -2
- package/src/__internal.ts +7 -1
- package/src/browser/action-coordinator.ts +2 -13
- package/src/browser/action-fence.ts +11 -3
- package/src/browser/connection-warmup.ts +3 -1
- package/src/browser/event-controller.ts +42 -3
- package/src/browser/history-state.ts +15 -13
- package/src/browser/intercept-utils.ts +51 -0
- package/src/browser/navigation-bridge.ts +34 -30
- package/src/browser/navigation-client.ts +21 -33
- package/src/browser/navigation-store.ts +25 -27
- package/src/browser/navigation-transaction.ts +7 -11
- package/src/browser/partial-update.ts +8 -0
- package/src/browser/prefetch/cache.ts +2 -1
- package/src/browser/prefetch/fetch.ts +8 -16
- package/src/browser/prefetch/queue.ts +4 -4
- package/src/browser/react/NavigationProvider.tsx +2 -1
- package/src/browser/react/filter-segment-order.ts +2 -2
- package/src/browser/rsc-router.tsx +17 -2
- package/src/browser/segment-reconciler.ts +66 -53
- package/src/browser/server-action-bridge.ts +265 -127
- package/src/browser/types.ts +2 -1
- package/src/browser/wire-protocol.ts +41 -0
- package/src/cache/cache-key-utils.ts +11 -5
- package/src/cache/cache-runtime.ts +110 -50
- package/src/cache/cache-scope.ts +110 -64
- package/src/cache/cf/cf-cache-constants.ts +2 -2
- package/src/cache/cf/cf-cache-store.ts +486 -874
- package/src/cache/cf/cf-kv-utils.ts +1 -1
- package/src/cache/document-cache.ts +42 -15
- package/src/cache/handle-snapshot.ts +19 -7
- package/src/cache/segment-codec.ts +55 -0
- package/src/cache/shell-snapshot.ts +2 -2
- package/src/cache/tag-invalidation.ts +21 -2
- package/src/cache/taint.ts +5 -3
- package/src/cache/types.ts +7 -3
- package/src/cache/vercel/vercel-cache-store.ts +243 -310
- package/src/handles/pushed-by.ts +1 -1
- package/src/prefetch-markers.ts +4 -7
- package/src/prerender/store.ts +76 -0
- package/src/prerender/warm-request.ts +8 -4
- package/src/prerender.ts +2 -2
- package/src/route-name.ts +8 -0
- package/src/router/error-handling.ts +4 -4
- package/src/router/instrument.ts +4 -3
- package/src/router/intercept-resolution.ts +77 -75
- package/src/router/loader-resolution.ts +5 -4
- package/src/router/match-api.ts +4 -5
- package/src/router/match-context.ts +33 -12
- package/src/router/match-handlers.ts +8 -20
- package/src/router/match-middleware/background-revalidation.ts +41 -53
- package/src/router/match-middleware/cache-lookup.ts +680 -720
- package/src/router/match-middleware/cache-store.ts +14 -12
- package/src/router/match-middleware/intercept-resolution.ts +3 -23
- package/src/router/match-middleware/segment-resolution.ts +34 -61
- package/src/router/match-result.ts +1 -20
- package/src/router/middleware.ts +69 -11
- package/src/router/navigation-snapshot.ts +4 -3
- package/src/router/prerender-match.ts +100 -44
- package/src/router/preview-match.ts +6 -41
- package/src/router/request-classification.ts +13 -7
- package/src/router/revalidation.ts +33 -7
- package/src/router/route-snapshot.ts +2 -5
- package/src/router/router-context.ts +14 -117
- package/src/router/router-interfaces.ts +8 -14
- package/src/router/segment-resolution/loader-cache.ts +14 -9
- package/src/router/segment-resolution/loader-mask.ts +5 -5
- package/src/router/segment-resolution/prefetch-deferral.ts +30 -27
- package/src/router/segment-resolution/resolution-pass.ts +137 -0
- package/src/router/segment-resolution/revalidation.ts +897 -776
- package/src/router/segment-resolution.ts +4 -13
- package/src/router/segment-wrappers.ts +51 -269
- package/src/router/telemetry.ts +5 -0
- package/src/router/types.ts +10 -0
- package/src/router.ts +12 -13
- package/src/rsc/full-payload.ts +6 -5
- package/src/rsc/handler-context.ts +8 -14
- package/src/rsc/handler.ts +126 -507
- package/src/rsc/json-route-result.ts +5 -9
- package/src/rsc/loader-fetch.ts +6 -5
- package/src/rsc/progressive-enhancement.ts +5 -0
- package/src/rsc/request-stages.ts +757 -0
- package/src/rsc/response-cache-serve.ts +10 -14
- package/src/rsc/response-route-handler.ts +13 -5
- package/src/rsc/rewrite-passes.ts +2 -1
- package/src/rsc/routine-plan.ts +1 -1
- package/src/rsc/rsc-rendering.ts +172 -349
- package/src/rsc/server-action.ts +87 -113
- package/src/rsc/shell-capture-constants.ts +3 -1
- package/src/rsc/shell-capture.ts +212 -169
- package/src/rsc/shell-serve.ts +121 -18
- package/src/rsc/ssr-setup.ts +5 -4
- package/src/segment-system.tsx +3 -3
- package/src/server/context.ts +22 -25
- package/src/server/handle-store.ts +55 -0
- package/src/server/render-pass.ts +291 -0
- package/src/server/request-context.ts +26 -115
- package/src/server/rewrite-trail.ts +6 -4
- package/src/ssr/index.tsx +1 -1
- package/src/ssr/ssr-root.tsx +1 -0
- package/src/testing/dispatch.ts +223 -710
- package/src/testing/e2e/page-helpers.ts +2 -2
- package/src/testing/serve-shell-request.ts +37 -32
- package/src/types/cache-types.ts +6 -3
- package/src/types/error-types.ts +9 -1
- package/src/types/handler-context.ts +21 -7
- package/src/types/segments.ts +1 -1
- package/src/vite/discovery/build-discovery-phase.ts +204 -0
- package/src/vite/discovery/build-env.ts +148 -0
- package/src/vite/discovery/bundle-scan-phase.ts +128 -0
- package/src/vite/discovery/dev-prerender-cache.ts +8 -3
- package/src/vite/discovery/dev-server-phase.ts +1776 -0
- package/src/vite/discovery/discover-routers.ts +1 -1
- package/src/vite/discovery/discovery-errors.ts +1 -1
- package/src/vite/discovery/prerender-collection.ts +24 -39
- package/src/vite/discovery/state.ts +15 -0
- package/src/vite/plugins/version-plugin.ts +1 -1
- package/src/vite/plugins/virtual-entries.ts +1 -1
- package/src/vite/router-discovery.ts +29 -2428
- package/src/vite/temp-rsc-server.ts +223 -0
- package/src/vite/utils/prerender-utils.ts +47 -0
- package/src/wire-params.ts +35 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +0 -72
- package/src/router/segment-resolution/fresh.ts +0 -945
package/src/rsc/server-action.ts
CHANGED
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
import { printServerError } from "../server/print-server-error.js";
|
|
25
25
|
import { observePhase, PHASES } from "../router/instrument.js";
|
|
26
26
|
import { resolveActionRefId } from "../router/is-action.js";
|
|
27
|
+
import { getInterceptSourceHeader } from "../router/navigation-snapshot.js";
|
|
28
|
+
import type { ActionContext } from "../router/types.js";
|
|
27
29
|
import type { TraceSpan } from "../router/tracing.js";
|
|
28
30
|
import { attachTransitionWhen } from "./attach-transition-when.js";
|
|
29
31
|
import { payloadLocation } from "./full-payload.js";
|
|
@@ -50,6 +52,8 @@ import {
|
|
|
50
52
|
import { warnNonRedirectActionResponse } from "./runtime-warnings.js";
|
|
51
53
|
import type { HandlerContext } from "./handler-context.js";
|
|
52
54
|
import type { MatchResult } from "../types.js";
|
|
55
|
+
import type { HandleData } from "../server/handle-store.js";
|
|
56
|
+
import { isRedirectResponse } from "../response-utils.js";
|
|
53
57
|
import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
|
|
54
58
|
|
|
55
59
|
/**
|
|
@@ -62,8 +66,8 @@ import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
|
|
|
62
66
|
* the revalidation phase so it runs INSIDE the same route-middleware wrapper as
|
|
63
67
|
* a successful revalidation — route middleware (context vars, headers, cookies)
|
|
64
68
|
* must apply to the error render too, matching the module doc's "identical to a
|
|
65
|
-
* normal render".
|
|
66
|
-
* boundary
|
|
69
|
+
* normal render". That render is the action's revalidation, cut at the
|
|
70
|
+
* boundary (ActionContext.boundary).
|
|
67
71
|
*/
|
|
68
72
|
export interface ActionContinuation {
|
|
69
73
|
returnValue: { ok: boolean; data: unknown };
|
|
@@ -195,6 +199,7 @@ export async function executeServerAction<TEnv>(
|
|
|
195
199
|
let returnValue: { ok: boolean; data: unknown };
|
|
196
200
|
let actionStatus = 200;
|
|
197
201
|
let loadedAction: Function | undefined;
|
|
202
|
+
let errorBoundary: MatchResult | undefined;
|
|
198
203
|
|
|
199
204
|
try {
|
|
200
205
|
loadedAction = await ctx.loadServerAction(actionId);
|
|
@@ -267,14 +272,13 @@ export async function executeServerAction<TEnv>(
|
|
|
267
272
|
|
|
268
273
|
// Try to render error boundary.
|
|
269
274
|
// Report the action error first so it is not lost if matchError throws.
|
|
270
|
-
|
|
275
|
+
// The boundary renders in the revalidation phase, so route middleware
|
|
276
|
+
// applies to it as to a success's render (handler.ts
|
|
277
|
+
// executeRenderWithMiddleware).
|
|
271
278
|
try {
|
|
272
|
-
|
|
273
|
-
request,
|
|
274
|
-
|
|
275
|
-
error,
|
|
276
|
-
"route",
|
|
277
|
-
);
|
|
279
|
+
errorBoundary =
|
|
280
|
+
(await ctx.router.matchError(request, { env }, error, "route")) ??
|
|
281
|
+
undefined;
|
|
278
282
|
} catch (matchErr) {
|
|
279
283
|
// matchError failed — report the original action error as unhandled,
|
|
280
284
|
// then let the matchError failure propagate.
|
|
@@ -293,32 +297,8 @@ export async function executeServerAction<TEnv>(
|
|
|
293
297
|
url,
|
|
294
298
|
env,
|
|
295
299
|
actionId,
|
|
296
|
-
handledByBoundary: !!
|
|
300
|
+
handledByBoundary: !!errorBoundary,
|
|
297
301
|
});
|
|
298
|
-
|
|
299
|
-
if (errorResult) {
|
|
300
|
-
// Defer the error-boundary render to the revalidation phase so it runs
|
|
301
|
-
// inside the same route-middleware wrapper as a successful revalidation
|
|
302
|
-
// (handler.ts executeRenderWithMiddleware). Building + returning the
|
|
303
|
-
// Response here would bypass route middleware: context vars, headers, and
|
|
304
|
-
// cookies set by route middleware would NOT apply to the error render,
|
|
305
|
-
// diverging from the success path and from the module doc's "identical to
|
|
306
|
-
// a normal render". The boundary is already matched; the render in
|
|
307
|
-
// revalidateAfterAction uses errorResult directly (no matchPartial).
|
|
308
|
-
return {
|
|
309
|
-
returnValue,
|
|
310
|
-
actionStatus,
|
|
311
|
-
temporaryReferences,
|
|
312
|
-
// actionContext is unused on the errorBoundary path (no matchPartial).
|
|
313
|
-
actionContext: {
|
|
314
|
-
actionId,
|
|
315
|
-
actionUrl: new URL(url),
|
|
316
|
-
actionResult: returnValue.data,
|
|
317
|
-
formData: actionFormData,
|
|
318
|
-
},
|
|
319
|
-
errorBoundary: errorResult,
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
302
|
}
|
|
323
303
|
|
|
324
304
|
// Build continuation for the revalidation phase
|
|
@@ -337,6 +317,7 @@ export async function executeServerAction<TEnv>(
|
|
|
337
317
|
actionResult: returnValue.data,
|
|
338
318
|
formData: actionFormData,
|
|
339
319
|
},
|
|
320
|
+
...(errorBoundary && { errorBoundary }),
|
|
340
321
|
};
|
|
341
322
|
}
|
|
342
323
|
|
|
@@ -456,9 +437,9 @@ async function revalidateAfterActionInner<TEnv>(
|
|
|
456
437
|
}
|
|
457
438
|
|
|
458
439
|
/**
|
|
459
|
-
* The action-revalidation plan:
|
|
460
|
-
* action threw
|
|
461
|
-
*
|
|
440
|
+
* The action-revalidation plan: match the affected segments, cut at the error
|
|
441
|
+
* boundary when the action threw into one (a full match for a redirect
|
|
442
|
+
* route), and render the partial payload.
|
|
462
443
|
*/
|
|
463
444
|
function* actionRevalidationPlan<TEnv>(
|
|
464
445
|
input: ActionRevalidationInput<TEnv>,
|
|
@@ -466,12 +447,14 @@ function* actionRevalidationPlan<TEnv>(
|
|
|
466
447
|
const { ctx, request, env, url, continuation } = input;
|
|
467
448
|
const { actionContext, errorBoundary } = continuation;
|
|
468
449
|
|
|
469
|
-
// Action threw and a boundary matched: render
|
|
470
|
-
//
|
|
471
|
-
// the success branch below.
|
|
450
|
+
// Action threw and a boundary matched: render it here so it runs inside the
|
|
451
|
+
// route-middleware wrapper, exactly like the success branch below.
|
|
472
452
|
if (errorBoundary) {
|
|
453
|
+
const boundaryResult = yield* step("match:partial", () =>
|
|
454
|
+
matchBoundaryRevalidation(input, errorBoundary),
|
|
455
|
+
);
|
|
473
456
|
return yield* step("render", () =>
|
|
474
|
-
|
|
457
|
+
renderActionResponse(input, boundaryResult),
|
|
475
458
|
);
|
|
476
459
|
}
|
|
477
460
|
|
|
@@ -510,9 +493,7 @@ function* actionRevalidationPlan<TEnv>(
|
|
|
510
493
|
);
|
|
511
494
|
}
|
|
512
495
|
|
|
513
|
-
return yield* step("render", () =>
|
|
514
|
-
renderRevalidationResponse(input, matchResult),
|
|
515
|
-
);
|
|
496
|
+
return yield* step("render", () => renderActionResponse(input, matchResult));
|
|
516
497
|
}
|
|
517
498
|
|
|
518
499
|
/** matchPartial that stamps params/routeName when a result exists. */
|
|
@@ -520,7 +501,7 @@ async function matchPartialAndRecord<TEnv>(
|
|
|
520
501
|
ctx: HandlerContext<TEnv>,
|
|
521
502
|
request: Request,
|
|
522
503
|
env: TEnv,
|
|
523
|
-
actionContext:
|
|
504
|
+
actionContext: ActionContext,
|
|
524
505
|
): Promise<
|
|
525
506
|
Awaited<ReturnType<HandlerContext<TEnv>["router"]["matchPartial"]>>
|
|
526
507
|
> {
|
|
@@ -536,82 +517,67 @@ async function matchPartialAndRecord<TEnv>(
|
|
|
536
517
|
}
|
|
537
518
|
|
|
538
519
|
/**
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
*
|
|
520
|
+
* A thrown action's boundary response: its revalidation, cut at the boundary
|
|
521
|
+
* (ActionContext.boundary). matchError's result alone, which streams no
|
|
522
|
+
* handle values, for an action sent from an intercept, and when the cut
|
|
523
|
+
* revalidation returns null, misses the boundary or throws anything but a
|
|
524
|
+
* redirect.
|
|
542
525
|
*/
|
|
543
|
-
function
|
|
544
|
-
|
|
526
|
+
async function matchBoundaryRevalidation<TEnv>(
|
|
527
|
+
{ ctx, request, env, continuation, reqCtx }: ActionRevalidationInput<TEnv>,
|
|
545
528
|
errorBoundary: MatchResult,
|
|
546
|
-
): Promise<
|
|
547
|
-
|
|
548
|
-
const
|
|
549
|
-
|
|
550
|
-
|
|
529
|
+
): Promise<MatchResult> {
|
|
530
|
+
// matchError returns the error segment alone.
|
|
531
|
+
const boundary = errorBoundary.segments[0]!;
|
|
532
|
+
if (!getInterceptSourceHeader(request)) {
|
|
533
|
+
let failure: string | undefined;
|
|
534
|
+
try {
|
|
535
|
+
const matchResult = await matchPartialAndRecord(ctx, request, env, {
|
|
536
|
+
...continuation.actionContext,
|
|
537
|
+
boundary,
|
|
538
|
+
});
|
|
539
|
+
if (
|
|
540
|
+
matchResult?.segments.some(
|
|
541
|
+
(s) => s.id === boundary.id && s.type === "error",
|
|
542
|
+
)
|
|
543
|
+
) {
|
|
544
|
+
return matchResult;
|
|
545
|
+
}
|
|
546
|
+
if (matchResult) failure = "did not reach the boundary";
|
|
547
|
+
} catch (error) {
|
|
548
|
+
// Redirects as from a success's revalidation (handler.ts
|
|
549
|
+
// executeRenderWithMiddleware). matchError's 500 was the boundary's.
|
|
550
|
+
if (error instanceof Response && isRedirectResponse(error)) {
|
|
551
|
+
reqCtx._setStatus(200);
|
|
552
|
+
throw error;
|
|
553
|
+
}
|
|
554
|
+
failure = `threw ${error instanceof Response ? `a ${error.status} Response` : String(error)}`;
|
|
555
|
+
}
|
|
556
|
+
if (failure && process.env.NODE_ENV !== "production") {
|
|
557
|
+
console.warn(
|
|
558
|
+
`[@rangojs/router] Server action "${continuation.actionContext.actionId}" ` +
|
|
559
|
+
`threw into an error boundary whose revalidation ${failure}. The ` +
|
|
560
|
+
`response carries the error segment alone, without the loaders above it.`,
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
551
564
|
setRequestContextParams(errorBoundary.params, errorBoundary.routeName);
|
|
552
|
-
|
|
553
|
-
const errorPayload: RscPayload = {
|
|
554
|
-
metadata: {
|
|
555
|
-
...payloadLocation(reqCtx, url),
|
|
556
|
-
// routerId exposed for the frontend (current app identity); see
|
|
557
|
-
// rsc-rendering.ts partial branch.
|
|
558
|
-
routerId: ctx.router.id,
|
|
559
|
-
segments: attachTransitionWhen(errorBoundary.segments, reqCtx),
|
|
560
|
-
isPartial: true,
|
|
561
|
-
matched: errorBoundary.matched,
|
|
562
|
-
diff: errorBoundary.diff,
|
|
563
|
-
resolvedIds: errorBoundary.resolvedIds,
|
|
564
|
-
params: errorBoundary.params,
|
|
565
|
-
routeName: publicRouteName(errorBoundary.routeName),
|
|
566
|
-
isError: true,
|
|
567
|
-
handles: handleStore.stream(),
|
|
568
|
-
version: ctx.version,
|
|
569
|
-
},
|
|
570
|
-
returnValue,
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
// Intentionally omit attachLocationState for error payloads: location state
|
|
574
|
-
// is a success-only semantic. Error boundary responses update the error UI
|
|
575
|
-
// but should not mutate browser history state.
|
|
576
|
-
|
|
577
|
-
return renderRscResponse({
|
|
578
|
-
ctx,
|
|
579
|
-
request,
|
|
580
|
-
env,
|
|
581
|
-
url,
|
|
582
|
-
payload: errorPayload,
|
|
583
|
-
temporaryReferences,
|
|
584
|
-
init: {
|
|
585
|
-
status: actionStatus,
|
|
586
|
-
headers: {
|
|
587
|
-
"content-type": "text/x-component;charset=utf-8",
|
|
588
|
-
// Router identity for the client's pre-decode integrity check (the
|
|
589
|
-
// action apply path has no post-decode guard). See response-adapter.
|
|
590
|
-
"X-RSC-Router-Id": ctx.router.id,
|
|
591
|
-
},
|
|
592
|
-
},
|
|
593
|
-
tracking: {
|
|
594
|
-
mode: "action-revalidation",
|
|
595
|
-
routeKey: input.reqCtx._routeName,
|
|
596
|
-
actionId: actionContext?.actionId,
|
|
597
|
-
span: input.renderSpan,
|
|
598
|
-
onEvent:
|
|
599
|
-
reqCtx._activeRoutine &&
|
|
600
|
-
createRenderStageTraceBridge(reqCtx._activeRoutine),
|
|
601
|
-
},
|
|
602
|
-
});
|
|
565
|
+
return errorBoundary;
|
|
603
566
|
}
|
|
604
567
|
|
|
605
|
-
/**
|
|
606
|
-
|
|
568
|
+
/**
|
|
569
|
+
* Render the action's revalidation, or a thrown action's boundary response.
|
|
570
|
+
* An error payload attaches no location state: that is a success-only
|
|
571
|
+
* semantic, and the boundary must not mutate history state.
|
|
572
|
+
*/
|
|
573
|
+
function renderActionResponse<TEnv>(
|
|
607
574
|
input: ActionRevalidationInput<TEnv>,
|
|
608
|
-
matchResult:
|
|
609
|
-
Awaited<ReturnType<HandlerContext<TEnv>["router"]["matchPartial"]>>
|
|
610
|
-
>,
|
|
575
|
+
matchResult: MatchResult,
|
|
611
576
|
): Promise<Response> {
|
|
612
577
|
const { ctx, request, env, url, handleStore, continuation, reqCtx } = input;
|
|
613
578
|
const { returnValue, actionStatus, temporaryReferences, actionContext } =
|
|
614
579
|
continuation;
|
|
580
|
+
const isError = !!continuation.errorBoundary;
|
|
615
581
|
|
|
616
582
|
const payload: RscPayload = {
|
|
617
583
|
metadata: {
|
|
@@ -627,13 +593,18 @@ function renderRevalidationResponse<TEnv>(
|
|
|
627
593
|
params: matchResult.params,
|
|
628
594
|
routeName: publicRouteName(matchResult.routeName),
|
|
629
595
|
slots: matchResult.slots,
|
|
630
|
-
|
|
596
|
+
...(isError && { isError }),
|
|
597
|
+
// matchError's result: the abandoned walk's pushes are not the page's.
|
|
598
|
+
handles:
|
|
599
|
+
matchResult === continuation.errorBoundary
|
|
600
|
+
? noHandles()
|
|
601
|
+
: handleStore.stream(),
|
|
631
602
|
version: ctx.version,
|
|
632
603
|
},
|
|
633
604
|
returnValue,
|
|
634
605
|
};
|
|
635
606
|
|
|
636
|
-
attachLocationStateIfPresent(payload);
|
|
607
|
+
if (!isError) attachLocationStateIfPresent(payload);
|
|
637
608
|
|
|
638
609
|
return renderRscResponse({
|
|
639
610
|
ctx,
|
|
@@ -662,3 +633,6 @@ function renderRevalidationResponse<TEnv>(
|
|
|
662
633
|
},
|
|
663
634
|
});
|
|
664
635
|
}
|
|
636
|
+
|
|
637
|
+
/** The handle stream of matchBoundaryRevalidation's fallback. */
|
|
638
|
+
async function* noHandles(): AsyncGenerator<HandleData, void, unknown> {}
|
|
@@ -52,6 +52,8 @@ export const PPR_REPLAY_STATUS_HEADER: string = "x-rango-ppr-replay";
|
|
|
52
52
|
*/
|
|
53
53
|
export const PPR_REPLAY_BYPASS_REASONS = [
|
|
54
54
|
"method",
|
|
55
|
+
// A stale request (`_rsc_stale`) renders live, as an action does.
|
|
56
|
+
"stale",
|
|
55
57
|
"dynamic",
|
|
56
58
|
"nonce",
|
|
57
59
|
"store-unavailable",
|
|
@@ -198,7 +200,7 @@ export const POST_QUIESCE_TASK_HOPS = 16;
|
|
|
198
200
|
* short is an acceptable loss — every terminal path backs the key off anyway),
|
|
199
201
|
* and below workerd's ~30s waitUntil grace so the cap timer still fires in a
|
|
200
202
|
* live context. When workerd kills the context BEFORE the cap fires, the timer
|
|
201
|
-
* dies with it — that stranding is healed by
|
|
203
|
+
* dies with it — that stranding is healed by planShellCapture's staleness
|
|
202
204
|
* check on the stampede guard, keyed off the same constant.
|
|
203
205
|
*/
|
|
204
206
|
export const SHELL_CAPTURE_TASK_HARD_CAP_MS = 25_000;
|