@timber-js/app 0.2.0-alpha.7 → 0.2.0-alpha.9

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 (67) hide show
  1. package/dist/_chunks/{tracing-Cwn7697K.js → tracing-CemImE6h.js} +16 -2
  2. package/dist/_chunks/{tracing-Cwn7697K.js.map → tracing-CemImE6h.js.map} +1 -1
  3. package/dist/adapters/nitro.d.ts.map +1 -1
  4. package/dist/adapters/nitro.js.map +1 -1
  5. package/dist/cache/fast-hash.d.ts +22 -0
  6. package/dist/cache/fast-hash.d.ts.map +1 -0
  7. package/dist/cache/index.js +51 -9
  8. package/dist/cache/index.js.map +1 -1
  9. package/dist/cache/register-cached-function.d.ts.map +1 -1
  10. package/dist/cache/timber-cache.d.ts.map +1 -1
  11. package/dist/client/index.js.map +1 -1
  12. package/dist/client/link.d.ts.map +1 -1
  13. package/dist/client/router.d.ts.map +1 -1
  14. package/dist/client/segment-context.d.ts +1 -1
  15. package/dist/client/segment-context.d.ts.map +1 -1
  16. package/dist/client/segment-merger.d.ts.map +1 -1
  17. package/dist/client/stale-reload.d.ts.map +1 -1
  18. package/dist/client/top-loader.d.ts.map +1 -1
  19. package/dist/client/transition-root.d.ts +1 -1
  20. package/dist/client/transition-root.d.ts.map +1 -1
  21. package/dist/index.d.ts +0 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +38 -34
  24. package/dist/index.js.map +1 -1
  25. package/dist/plugins/fonts.d.ts +7 -0
  26. package/dist/plugins/fonts.d.ts.map +1 -1
  27. package/dist/server/action-client.d.ts.map +1 -1
  28. package/dist/server/index.js +9 -1
  29. package/dist/server/index.js.map +1 -1
  30. package/dist/server/pipeline.d.ts.map +1 -1
  31. package/dist/server/response-cache.d.ts +5 -4
  32. package/dist/server/response-cache.d.ts.map +1 -1
  33. package/dist/server/route-element-builder.d.ts.map +1 -1
  34. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  35. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  36. package/dist/server/rsc-entry/rsc-stream.d.ts +6 -0
  37. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  38. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  39. package/dist/server/tracing.d.ts +10 -0
  40. package/dist/server/tracing.d.ts.map +1 -1
  41. package/dist/server/waituntil-bridge.d.ts.map +1 -1
  42. package/package.json +1 -1
  43. package/src/adapters/nitro.ts +6 -1
  44. package/src/cache/fast-hash.ts +34 -0
  45. package/src/cache/register-cached-function.ts +7 -3
  46. package/src/cache/timber-cache.ts +17 -10
  47. package/src/client/browser-entry.ts +10 -6
  48. package/src/client/link.tsx +14 -9
  49. package/src/client/router.ts +4 -6
  50. package/src/client/segment-context.ts +6 -1
  51. package/src/client/segment-merger.ts +2 -8
  52. package/src/client/stale-reload.ts +4 -6
  53. package/src/client/top-loader.tsx +8 -7
  54. package/src/client/transition-root.tsx +7 -1
  55. package/src/index.ts +1 -2
  56. package/src/plugins/entries.ts +1 -1
  57. package/src/plugins/fonts.ts +54 -43
  58. package/src/server/action-client.ts +7 -1
  59. package/src/server/pipeline.ts +7 -0
  60. package/src/server/response-cache.ts +169 -36
  61. package/src/server/route-element-builder.ts +1 -6
  62. package/src/server/rsc-entry/index.ts +9 -6
  63. package/src/server/rsc-entry/rsc-payload.ts +42 -10
  64. package/src/server/rsc-entry/rsc-stream.ts +9 -5
  65. package/src/server/rsc-entry/ssr-renderer.ts +11 -8
  66. package/src/server/tracing.ts +23 -0
  67. package/src/server/waituntil-bridge.ts +4 -1
@@ -156,16 +156,19 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
156
156
  try {
157
157
  const ssrResponse = await callSsr(ssrStream, navContext);
158
158
 
159
- // Signal promotion: yield one microtask so async component rejections
160
- // propagate to the RSC onError callback, then check if any signals
161
- // were captured during rendering inside Suspense boundaries.
162
- // The Response hasn't been sent yet — it's an unconsumed stream.
159
+ // Signal promotion: check if any signals were captured during rendering
160
+ // inside Suspense boundaries. If no signals are present yet, yield one
161
+ // microtask so async component rejections propagate to the RSC onError
162
+ // callback before we commit the response.
163
163
  //
164
- // Uses queueMicrotask instead of setTimeout(0) to avoid yielding to
165
- // the full event loop (timers phase). Microtask resolution happens
166
- // within the same tick, eliminating per-request idle time under load.
164
+ // When signals are already captured (onSignal already fired), skip the
165
+ // yield entirely react immediately. Uses queueMicrotask instead of
166
+ // setTimeout(0) for the fallback to avoid yielding to the full event
167
+ // loop (timers phase).
167
168
  // See design/05-streaming.md §"deferSuspenseFor and the Hold Window"
168
- await new Promise<void>((r) => queueMicrotask(r));
169
+ if (!signals.redirectSignal && !signals.denySignal && !signals.renderError) {
170
+ await new Promise<void>((r) => queueMicrotask(r));
171
+ }
169
172
 
170
173
  const promoted = checkCapturedSignals(/* skipHandledDeny */ true);
171
174
  if (promoted) {
@@ -252,6 +252,29 @@ export async function addSpanEvent(
252
252
  }
253
253
  }
254
254
 
255
+ /**
256
+ * Fire-and-forget span event — no await, no microtask overhead.
257
+ *
258
+ * Used on the cache hot path where awaiting addSpanEvent creates an
259
+ * unnecessary microtask per cache operation. If OTEL is not loaded yet,
260
+ * the event is silently dropped (acceptable for diagnostics).
261
+ *
262
+ * See TIM-370 for perf motivation.
263
+ */
264
+ export function addSpanEventSync(
265
+ name: string,
266
+ attributes?: Record<string, string | number | boolean>
267
+ ): void {
268
+ // Fast path: if OTEL API hasn't been loaded yet, skip entirely.
269
+ // _otelApi is undefined (not yet loaded), null (failed to load), or the module.
270
+ if (!_otelApi) return;
271
+
272
+ const activeSpan = _otelApi.trace.getActiveSpan();
273
+ if (activeSpan) {
274
+ activeSpan.addEvent(name, attributes);
275
+ }
276
+ }
277
+
255
278
  /**
256
279
  * Try to extract the OTEL trace ID from the current active span context.
257
280
  * Returns undefined if OTEL is not active or no span exists.
@@ -18,7 +18,10 @@ import { waitUntilAls } from './als-registry.js';
18
18
  * Called by generated entry points (Nitro node-server/bun, Cloudflare)
19
19
  * to bind the platform's lifecycle extension for the request duration.
20
20
  */
21
- export function runWithWaitUntil<T>(waitUntilFn: (promise: Promise<unknown>) => void, fn: () => T): T {
21
+ export function runWithWaitUntil<T>(
22
+ waitUntilFn: (promise: Promise<unknown>) => void,
23
+ fn: () => T
24
+ ): T {
22
25
  return waitUntilAls.run(waitUntilFn, fn);
23
26
  }
24
27