@timber-js/app 0.1.51 → 0.1.53

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.
Files changed (37) hide show
  1. package/dist/adapters/compress-module.d.ts.map +1 -1
  2. package/dist/adapters/nitro.d.ts.map +1 -1
  3. package/dist/adapters/nitro.js +22 -8
  4. package/dist/adapters/nitro.js.map +1 -1
  5. package/dist/client/index.js +248 -22
  6. package/dist/client/index.js.map +1 -1
  7. package/dist/client/router.d.ts +6 -0
  8. package/dist/client/router.d.ts.map +1 -1
  9. package/dist/client/rsc-fetch.d.ts +80 -0
  10. package/dist/client/rsc-fetch.d.ts.map +1 -0
  11. package/dist/client/segment-cache.d.ts +2 -0
  12. package/dist/client/segment-cache.d.ts.map +1 -1
  13. package/dist/client/segment-merger.d.ts +96 -0
  14. package/dist/client/segment-merger.d.ts.map +1 -0
  15. package/dist/client/stale-reload.d.ts +44 -0
  16. package/dist/client/stale-reload.d.ts.map +1 -0
  17. package/dist/index.js +15 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/server/compress.d.ts.map +1 -1
  20. package/dist/server/route-element-builder.d.ts +7 -0
  21. package/dist/server/route-element-builder.d.ts.map +1 -1
  22. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  23. package/dist/server/rsc-entry/rsc-payload.d.ts +1 -1
  24. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  25. package/package.json +1 -1
  26. package/src/adapters/compress-module.ts +18 -5
  27. package/src/adapters/nitro.ts +4 -3
  28. package/src/client/browser-entry.ts +68 -8
  29. package/src/client/router.ts +48 -188
  30. package/src/client/rsc-fetch.ts +234 -0
  31. package/src/client/segment-cache.ts +2 -0
  32. package/src/client/segment-merger.ts +297 -0
  33. package/src/client/stale-reload.ts +89 -0
  34. package/src/server/compress.ts +23 -4
  35. package/src/server/route-element-builder.ts +14 -0
  36. package/src/server/rsc-entry/index.ts +3 -2
  37. package/src/server/rsc-entry/rsc-payload.ts +8 -1
@@ -61,6 +61,13 @@ export interface RouteElementResult {
61
61
  segments: ManifestSegmentNode[];
62
62
  /** Max deferSuspenseFor hold window across all segments. */
63
63
  deferSuspenseFor: number;
64
+ /**
65
+ * Segment paths that were skipped because the client already has them cached.
66
+ * Ordered outermost to innermost. Empty when no segments were skipped.
67
+ * The client uses this to merge the partial payload with cached segments.
68
+ * See design/19-client-navigation.md §"X-Timber-State-Tree Header"
69
+ */
70
+ skippedSegments: string[];
64
71
  }
65
72
 
66
73
  /**
@@ -305,6 +312,10 @@ export async function buildRouteElement(
305
312
  layoutComponents.map(({ component, segment }) => [segment, component])
306
313
  );
307
314
 
315
+ // Track which segments were skipped for the X-Timber-Skipped-Segments header.
316
+ // The client uses this to merge the partial payload with its cached segments.
317
+ const skippedSegments: string[] = [];
318
+
308
319
  // Wrap from innermost (leaf) to outermost (root), processing every
309
320
  // segment in the chain. Each segment may contribute:
310
321
  // 1. Error boundaries (status files + error.tsx)
@@ -334,6 +345,8 @@ export async function buildRouteElement(
334
345
  // Skip this segment entirely — the client uses its cached version.
335
346
  // Access.ts already ran in the pre-render loop (security guarantee).
336
347
  // Metadata was already resolved above (head elements are correct).
348
+ // Record for X-Timber-Skipped-Segments header (outermost first, so prepend).
349
+ skippedSegments.unshift(segment.urlPath);
337
350
  continue;
338
351
  }
339
352
 
@@ -413,5 +426,6 @@ export async function buildRouteElement(
413
426
  layoutComponents,
414
427
  segments,
415
428
  deferSuspenseFor,
429
+ skippedSegments,
416
430
  };
417
431
  }
@@ -330,7 +330,7 @@ async function renderRoute(
330
330
  throw error;
331
331
  }
332
332
 
333
- const { element, headElements, layoutComponents, deferSuspenseFor } = routeResult;
333
+ const { element, headElements, layoutComponents, deferSuspenseFor, skippedSegments } = routeResult;
334
334
 
335
335
  // Build head HTML for injection into the SSR output.
336
336
  // Collects CSS, fonts, and modulepreload from the build manifest for matched segments.
@@ -434,7 +434,8 @@ async function renderRoute(
434
434
  layoutComponents,
435
435
  headElements,
436
436
  match,
437
- responseHeaders
437
+ responseHeaders,
438
+ skippedSegments
438
439
  );
439
440
  }
440
441
 
@@ -41,7 +41,8 @@ export async function buildRscPayloadResponse(
41
41
  layoutComponents: LayoutComponentEntry[],
42
42
  headElements: HeadElement[],
43
43
  match: RouteMatch,
44
- responseHeaders: Headers
44
+ responseHeaders: Headers,
45
+ skippedSegments?: string[]
45
46
  ): Promise<Response> {
46
47
  // Read the first chunk from the RSC stream before committing headers.
47
48
  const reader = rscStream.getReader();
@@ -113,6 +114,12 @@ export async function buildRscPayloadResponse(
113
114
  const segmentInfo = buildSegmentInfo(segments, layoutComponents);
114
115
  responseHeaders.set('X-Timber-Segments', JSON.stringify(segmentInfo));
115
116
 
117
+ // Send skipped segments so the client can merge the partial RSC payload
118
+ // with its cached segment elements. See design/19-client-navigation.md.
119
+ if (skippedSegments && skippedSegments.length > 0) {
120
+ responseHeaders.set('X-Timber-Skipped-Segments', JSON.stringify(skippedSegments));
121
+ }
122
+
116
123
  // Send route params so the client can populate useParams() after
117
124
  // SPA navigation. Without this, useParams() returns {}.
118
125
  if (Object.keys(match.params).length > 0) {