@timber-js/app 0.2.0-alpha.7 → 0.2.0-alpha.71
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/LICENSE +8 -0
- package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-BJARkOcu.js} +1 -1
- package/dist/_chunks/als-registry-BJARkOcu.js.map +1 -0
- package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
- package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
- package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
- package/dist/_chunks/define-CGuYoRHU.js +199 -0
- package/dist/_chunks/define-CGuYoRHU.js.map +1 -0
- package/dist/_chunks/define-Dz1bqwaS.js +106 -0
- package/dist/_chunks/define-Dz1bqwaS.js.map +1 -0
- package/dist/_chunks/define-cookie-B5mewxwM.js +93 -0
- package/dist/_chunks/define-cookie-B5mewxwM.js.map +1 -0
- package/dist/_chunks/error-boundary-D9hzsveV.js +216 -0
- package/dist/_chunks/error-boundary-D9hzsveV.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → format-Rn922VH2.js} +3 -20
- package/dist/_chunks/format-Rn922VH2.js.map +1 -0
- package/dist/_chunks/{tracing-Cwn7697K.js → handler-store-BVePM7hp.js} +68 -3
- package/dist/_chunks/handler-store-BVePM7hp.js.map +1 -0
- package/dist/_chunks/{interception-BOoWmLUA.js → interception-CEdHHviP.js} +171 -97
- package/dist/_chunks/interception-CEdHHviP.js.map +1 -0
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
- package/dist/_chunks/{request-context-DIkVh_jG.js → request-context-CywiO4jV.js} +181 -69
- package/dist/_chunks/request-context-CywiO4jV.js.map +1 -0
- package/dist/_chunks/schema-bridge-C4SwjCQD.js +86 -0
- package/dist/_chunks/schema-bridge-C4SwjCQD.js.map +1 -0
- package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
- package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
- package/dist/_chunks/segment-context-hzuJ048X.js +72 -0
- package/dist/_chunks/segment-context-hzuJ048X.js.map +1 -0
- package/dist/_chunks/stale-reload-BLUC_Pl_.js +64 -0
- package/dist/_chunks/stale-reload-BLUC_Pl_.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-DAhgj8Gx.js} +1 -1
- package/dist/_chunks/use-query-states-DAhgj8Gx.js.map +1 -0
- package/dist/_chunks/wrappers-LZbghvn0.js +63 -0
- package/dist/_chunks/wrappers-LZbghvn0.js.map +1 -0
- package/dist/adapters/cloudflare-dev.d.ts +109 -0
- package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +73 -0
- package/dist/adapters/cloudflare-dev.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +148 -12
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +135 -11
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +17 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +56 -13
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/cache/cache-api.d.ts +24 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/fast-hash.d.ts +22 -0
- package/dist/cache/fast-hash.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +31 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +7 -5
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +111 -73
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/singleflight.d.ts +18 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/client/error-boundary.d.ts +12 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -125
- package/dist/client/error-reconstituter.d.ts +54 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +2 -2
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +19 -4
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +6 -5
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +537 -166
- package/dist/client/index.js.map +1 -1
- package/dist/client/link-pending-store.d.ts +78 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +90 -32
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/nav-link-store.d.ts +36 -0
- package/dist/client/nav-link-store.d.ts.map +1 -0
- package/dist/client/navigation-api-types.d.ts +90 -0
- package/dist/client/navigation-api-types.d.ts.map +1 -0
- package/dist/client/navigation-api.d.ts +115 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +13 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/router.d.ts +70 -4
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +38 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +1 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-context.d.ts +1 -1
- package/dist/client/segment-context.d.ts.map +1 -1
- package/dist/client/segment-merger.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +63 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +13 -4
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +3 -3
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-params.d.ts +6 -4
- package/dist/client/use-params.d.ts.map +1 -1
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/codec.d.ts +23 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +2 -0
- package/dist/cookies/define-cookie.d.ts +35 -14
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.d.ts +2 -0
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +3 -84
- package/dist/fonts/css.d.ts +1 -0
- package/dist/fonts/css.d.ts.map +1 -1
- package/dist/index.d.ts +154 -38
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12092 -11916
- package/dist/index.js.map +1 -1
- package/dist/plugins/adapter-build.d.ts +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +2 -2
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +3 -3
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +32 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-browser-logs.d.ts +84 -0
- package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
- package/dist/plugins/dev-error-overlay.d.ts +26 -1
- package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
- package/dist/plugins/dev-logs.d.ts +1 -1
- package/dist/plugins/dev-logs.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +19 -5
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +1 -1
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/routing.d.ts +1 -1
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts +6 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +1 -1
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen.d.ts +2 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/index.d.ts +2 -0
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +3 -2
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/segment-classify.d.ts +46 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/status-file-lint.d.ts +2 -1
- package/dist/routing/status-file-lint.d.ts.map +1 -1
- package/dist/routing/types.d.ts +16 -4
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +12 -0
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +76 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +139 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -6
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +4 -474
- package/dist/search-params/registry.d.ts +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/segment-params/define.d.ts +78 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +7 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +4 -0
- package/dist/server/access-gate.d.ts +4 -0
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +12 -1
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-encryption.d.ts +76 -0
- package/dist/server/action-encryption.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +3 -6
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +32 -4
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +2 -2
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/debug.d.ts +1 -1
- package/dist/server/default-logger.d.ts +22 -0
- package/dist/server/default-logger.d.ts.map +1 -0
- package/dist/server/deny-page-resolver.d.ts +52 -0
- package/dist/server/deny-page-resolver.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-warnings.d.ts +0 -14
- package/dist/server/dev-warnings.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -5
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +4 -3
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/flight-injection-state.d.ts +66 -0
- package/dist/server/flight-injection-state.d.ts.map +1 -0
- package/dist/server/flight-scripts.d.ts +42 -0
- package/dist/server/flight-scripts.d.ts.map +1 -0
- package/dist/server/flush.d.ts.map +1 -1
- package/dist/server/form-data.d.ts +29 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injectors.d.ts +51 -11
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2176 -1663
- package/dist/server/index.js.map +1 -1
- package/dist/server/logger.d.ts +25 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +19 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +113 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/page-deny-boundary.d.ts +31 -0
- package/dist/server/page-deny-boundary.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +1 -1
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-metadata.d.ts +6 -0
- package/dist/server/pipeline-metadata.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +32 -10
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +30 -3
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/render-timeout.d.ts +51 -0
- package/dist/server/render-timeout.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +76 -37
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +27 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +9 -2
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/api-handler.d.ts +2 -2
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +48 -5
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +8 -3
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +10 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sitemap-generator.d.ts +129 -0
- package/dist/server/sitemap-generator.d.ts.map +1 -0
- package/dist/server/sitemap-handler.d.ts +22 -0
- package/dist/server/sitemap-handler.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +22 -0
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +39 -21
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +50 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/status-code-resolver.d.ts +1 -1
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +36 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +10 -0
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +22 -19
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +1 -4
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/server/waituntil-bridge.d.ts.map +1 -1
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.js +42 -0
- package/dist/shims/font-google.js.map +1 -0
- package/dist/shims/font-local.d.ts +26 -0
- package/dist/shims/font-local.d.ts.map +1 -0
- package/dist/shims/font-local.js +20 -0
- package/dist/shims/font-local.js.map +1 -0
- package/dist/shims/navigation-client.d.ts +1 -1
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +1 -1
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/utils/directive-parser.d.ts +5 -2
- package/dist/utils/directive-parser.d.ts.map +1 -1
- package/dist/utils/state-machine.d.ts +80 -0
- package/dist/utils/state-machine.d.ts.map +1 -0
- package/package.json +37 -17
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare.ts +342 -28
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +58 -9
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +38 -0
- package/src/cache/fast-hash.ts +34 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +9 -5
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/timber-cache.ts +40 -29
- package/src/cli.ts +0 -0
- package/src/client/browser-entry.ts +314 -142
- package/src/client/error-boundary.tsx +48 -16
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +2 -2
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +13 -4
- package/src/client/link-pending-store.ts +136 -0
- package/src/client/link.tsx +346 -105
- package/src/client/nav-link-store.ts +47 -0
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +332 -0
- package/src/client/navigation-context.ts +27 -6
- package/src/client/navigation-root.tsx +346 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router.ts +302 -77
- package/src/client/rsc-fetch.ts +93 -5
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-context.ts +6 -1
- package/src/client/segment-merger.ts +2 -8
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +73 -6
- package/src/client/top-loader.tsx +22 -13
- package/src/client/use-navigation-pending.ts +1 -1
- package/src/client/use-params.ts +7 -5
- package/src/client/use-query-states.ts +2 -2
- package/src/codec.ts +34 -0
- package/src/cookies/define-cookie.ts +72 -21
- package/src/cookies/index.ts +7 -0
- package/src/fonts/css.ts +2 -1
- package/src/index.ts +328 -92
- package/src/plugins/adapter-build.ts +8 -2
- package/src/plugins/build-manifest.ts +13 -2
- package/src/plugins/build-report.ts +3 -3
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-browser-logs.ts +288 -0
- package/src/plugins/dev-error-overlay.ts +70 -1
- package/src/plugins/dev-logs.ts +1 -1
- package/src/plugins/dev-server.ts +55 -9
- package/src/plugins/entries.ts +70 -9
- package/src/plugins/fonts.ts +167 -61
- package/src/plugins/mdx.ts +1 -1
- package/src/plugins/routing.ts +57 -17
- package/src/plugins/server-action-exports.ts +1 -1
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +76 -33
- package/src/plugins/static-build.ts +10 -6
- package/src/routing/codegen.ts +165 -105
- package/src/routing/index.ts +2 -0
- package/src/routing/scanner.ts +93 -23
- package/src/routing/segment-classify.ts +89 -0
- package/src/routing/status-file-lint.ts +3 -2
- package/src/routing/types.ts +17 -4
- package/src/rsc-runtime/rsc.ts +2 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
- package/src/search-params/define.ts +482 -0
- package/src/search-params/index.ts +13 -19
- package/src/search-params/registry.ts +1 -1
- package/src/search-params/wrappers.ts +85 -0
- package/src/segment-params/define.ts +279 -0
- package/src/segment-params/index.ts +28 -0
- package/src/server/access-gate.tsx +70 -29
- package/src/server/action-client.ts +28 -3
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +20 -3
- package/src/server/actions.ts +10 -9
- package/src/server/als-registry.ts +32 -4
- package/src/server/build-manifest.ts +10 -4
- package/src/server/compress.ts +25 -7
- package/src/server/debug.ts +1 -1
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-page-resolver.ts +154 -0
- package/src/server/deny-renderer.ts +24 -38
- package/src/server/dev-warnings.ts +2 -28
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +74 -22
- package/src/server/fallback-error.ts +31 -15
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/flush.ts +2 -1
- package/src/server/form-data.ts +76 -0
- package/src/server/html-injectors.ts +277 -117
- package/src/server/index.ts +9 -5
- package/src/server/logger.ts +44 -36
- package/src/server/middleware-runner.ts +31 -4
- package/src/server/node-stream-transforms.ts +509 -0
- package/src/server/page-deny-boundary.tsx +56 -0
- package/src/server/pipeline-interception.ts +17 -16
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline.ts +195 -51
- package/src/server/primitives.ts +47 -5
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +240 -117
- package/src/server/route-element-builder.ts +284 -197
- package/src/server/route-handler.ts +24 -4
- package/src/server/route-matcher.ts +24 -20
- package/src/server/rsc-entry/api-handler.ts +15 -16
- package/src/server/rsc-entry/error-renderer.ts +300 -89
- package/src/server/rsc-entry/helpers.ts +134 -5
- package/src/server/rsc-entry/index.ts +202 -113
- package/src/server/rsc-entry/rsc-payload.ts +100 -21
- package/src/server/rsc-entry/rsc-stream.ts +74 -18
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +173 -40
- package/src/server/safe-load.ts +60 -0
- package/src/server/sitemap-generator.ts +338 -0
- package/src/server/sitemap-handler.ts +126 -0
- package/src/server/slot-resolver.ts +243 -228
- package/src/server/ssr-entry.ts +211 -32
- package/src/server/ssr-render.ts +289 -67
- package/src/server/ssr-wrappers.tsx +139 -0
- package/src/server/status-code-resolver.ts +1 -1
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +37 -3
- package/src/server/tree-builder.ts +92 -58
- package/src/server/types.ts +3 -6
- package/src/server/version-skew.ts +104 -0
- package/src/server/waituntil-bridge.ts +4 -1
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/navigation-client.ts +1 -1
- package/src/shims/navigation.ts +2 -1
- package/src/utils/directive-parser.ts +5 -2
- package/src/utils/state-machine.ts +111 -0
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
- package/dist/_chunks/format-DviM89f0.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
- package/dist/_chunks/ssr-data-MjmprTmO.js +0 -88
- package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
- package/dist/_chunks/tracing-Cwn7697K.js.map +0 -1
- package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
- package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/cache/register-cached-function.d.ts +0 -17
- package/dist/cache/register-cached-function.d.ts.map +0 -1
- package/dist/client/error-boundary.js.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/cookies/index.js.map +0 -1
- package/dist/plugins/cache-transform.d.ts +0 -36
- package/dist/plugins/cache-transform.d.ts.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.d.ts.map +0 -1
- package/dist/search-params/analyze.d.ts +0 -54
- package/dist/search-params/analyze.d.ts.map +0 -1
- package/dist/search-params/builtin-codecs.d.ts +0 -105
- package/dist/search-params/builtin-codecs.d.ts.map +0 -1
- package/dist/search-params/codecs.d.ts +0 -53
- package/dist/search-params/codecs.d.ts.map +0 -1
- package/dist/search-params/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/search-params/index.js.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/server/response-cache.d.ts +0 -53
- package/dist/server/response-cache.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -99
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/transition-root.tsx +0 -160
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/search-params/analyze.ts +0 -192
- package/src/search-params/builtin-codecs.ts +0 -228
- package/src/search-params/create.ts +0 -321
- package/src/server/prerender.ts +0 -139
- package/src/server/response-cache.ts +0 -277
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client chunk grouping strategy for @vitejs/plugin-rsc.
|
|
3
|
+
*
|
|
4
|
+
* Groups client reference modules by layout boundary to balance route-scoped
|
|
5
|
+
* code splitting with HTTP request count. A constant group name would collapse
|
|
6
|
+
* all routes into one chunk (every page downloads every client component).
|
|
7
|
+
* Per-serverChunk grouping creates many sub-500B files. Layout-boundary
|
|
8
|
+
* grouping is the middle ground.
|
|
9
|
+
*
|
|
10
|
+
* See design/27-chunking-strategy.md, TIM-440, TIM-499.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Derive a chunk group name for a client reference module.
|
|
15
|
+
*
|
|
16
|
+
* Groups by the first non-group route segment under appDir so that all
|
|
17
|
+
* client components belonging to the same layout boundary land in one
|
|
18
|
+
* chunk. For example:
|
|
19
|
+
* - `facade:app/dashboard/settings/page.tsx` → `"client-dashboard"`
|
|
20
|
+
* - `facade:app/(group-a)/group-page-a/page.tsx` → `"client-group-page-a"`
|
|
21
|
+
* - `facade:app/layout.tsx` (root layout) → `"client-shared"`
|
|
22
|
+
* - `shared:...` (shared across chunks) → `"client-shared"`
|
|
23
|
+
*
|
|
24
|
+
* This balances route-scoped code splitting with HTTP request count:
|
|
25
|
+
* fewer chunks than per-serverChunk, but still avoids downloading every
|
|
26
|
+
* client component on every page.
|
|
27
|
+
*/
|
|
28
|
+
export function clientChunkGroup(
|
|
29
|
+
meta: { id: string; normalizedId: string; serverChunk: string },
|
|
30
|
+
appDir: string
|
|
31
|
+
): string {
|
|
32
|
+
const { normalizedId, serverChunk } = meta;
|
|
33
|
+
|
|
34
|
+
// Shared chunks (not associated with a single route entry) get one group.
|
|
35
|
+
if (serverChunk.startsWith('shared:')) return 'client-shared';
|
|
36
|
+
|
|
37
|
+
// Derive the layout boundary from the file's location relative to the
|
|
38
|
+
// app directory. normalizedId is root-relative (e.g. "app/dashboard/shell.tsx"
|
|
39
|
+
// or "src/app/dashboard/shell.tsx"). We find the "app/" prefix and walk
|
|
40
|
+
// segments after it to find the first non-group directory.
|
|
41
|
+
const relPath = normalizedId.replace(/\\/g, '/');
|
|
42
|
+
|
|
43
|
+
// Find the app directory boundary in the path. The last segment of appDir
|
|
44
|
+
// is the app folder name (usually "app").
|
|
45
|
+
const appDirName = appDir.replace(/\\/g, '/').split('/').pop() || 'app';
|
|
46
|
+
const appIdx = relPath.indexOf(appDirName + '/');
|
|
47
|
+
if (appIdx === -1) return 'client-shared';
|
|
48
|
+
|
|
49
|
+
const withinApp = relPath.slice(appIdx + appDirName.length + 1);
|
|
50
|
+
const segments = withinApp.split('/');
|
|
51
|
+
|
|
52
|
+
// Find first directory segment that isn't a route group like (group-a)
|
|
53
|
+
for (const seg of segments) {
|
|
54
|
+
// Skip the filename itself
|
|
55
|
+
if (seg.includes('.')) break;
|
|
56
|
+
// Skip route groups — parenthesized segments like (group-a)
|
|
57
|
+
if (seg.startsWith('(') && seg.endsWith(')')) continue;
|
|
58
|
+
// Found a real route segment
|
|
59
|
+
return `client-${seg}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Root-level files (layout.tsx, page.tsx directly in app/) go into the
|
|
63
|
+
// shared group since the root layout is loaded on every page.
|
|
64
|
+
return 'client-shared';
|
|
65
|
+
}
|
package/src/plugins/content.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import type { Plugin } from 'vite';
|
|
12
12
|
import { existsSync } from 'node:fs';
|
|
13
13
|
import { join } from 'node:path';
|
|
14
|
-
import type { PluginContext } from '
|
|
14
|
+
import type { PluginContext } from '../index.js';
|
|
15
15
|
|
|
16
16
|
const CONFIG_FILE_NAMES = [
|
|
17
17
|
'content-collections.ts',
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* timber-dev-browser-logs — Forwards browser console output to the server terminal.
|
|
3
|
+
*
|
|
4
|
+
* Injects a small inline script in dev mode that intercepts browser
|
|
5
|
+
* `console.error`, `console.warn`, and `console.info`, then forwards
|
|
6
|
+
* messages to the server via Vite's HMR WebSocket.
|
|
7
|
+
*
|
|
8
|
+
* The server-side listener formats and prints the messages with color-coded
|
|
9
|
+
* prefixes: [browser:error], [browser:warn], [browser:info].
|
|
10
|
+
*
|
|
11
|
+
* Dev-only: this plugin only runs during `vite dev`.
|
|
12
|
+
* No runtime overhead in production.
|
|
13
|
+
*
|
|
14
|
+
* See TIM-513 for design context.
|
|
15
|
+
* See design/18-build-system.md §"Dev Server" for sub-plugin architecture.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { Plugin, ViteDevServer } from 'vite';
|
|
19
|
+
import type { PluginContext } from '../index.js';
|
|
20
|
+
|
|
21
|
+
// ─── Types ───────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
/** Log levels forwarded from the browser. */
|
|
24
|
+
export type BrowserLogLevel = 'error' | 'warn' | 'info';
|
|
25
|
+
|
|
26
|
+
/** Configuration value for devBrowserLogs in timber.config.ts. */
|
|
27
|
+
export type DevBrowserLogsConfig = BrowserLogLevel | 'none' | undefined;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Payload sent from browser to server via Vite's HMR WebSocket.
|
|
31
|
+
* Kept small — truncated before sending.
|
|
32
|
+
*/
|
|
33
|
+
export interface BrowserLogPayload {
|
|
34
|
+
level: BrowserLogLevel;
|
|
35
|
+
/** Serialized message string. */
|
|
36
|
+
message: string;
|
|
37
|
+
/** Error stack trace, if the first argument was an Error. */
|
|
38
|
+
stack: string | null;
|
|
39
|
+
/** Source URL and line number, if available. */
|
|
40
|
+
source: string | null;
|
|
41
|
+
/** Timestamp in ms (Date.now()) from the browser. */
|
|
42
|
+
timestamp: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ─── Constants ───────────────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
/** Max message size in bytes before truncation. */
|
|
48
|
+
const MAX_MESSAGE_BYTES = 2048;
|
|
49
|
+
|
|
50
|
+
/** HMR event name for browser→server log forwarding. */
|
|
51
|
+
const HMR_EVENT = 'timber:browser-log';
|
|
52
|
+
|
|
53
|
+
/** ANSI color codes for terminal output. */
|
|
54
|
+
const COLORS = {
|
|
55
|
+
red: '\x1b[31m',
|
|
56
|
+
yellow: '\x1b[33m',
|
|
57
|
+
blue: '\x1b[34m',
|
|
58
|
+
dim: '\x1b[2m',
|
|
59
|
+
reset: '\x1b[0m',
|
|
60
|
+
} as const;
|
|
61
|
+
|
|
62
|
+
/** Level severity ordering for threshold comparison. */
|
|
63
|
+
const LEVEL_SEVERITY: Record<BrowserLogLevel | 'none', number> = {
|
|
64
|
+
none: 0,
|
|
65
|
+
info: 1,
|
|
66
|
+
warn: 2,
|
|
67
|
+
error: 3,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// ─── Formatting ──────────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Format a browser log payload for server terminal output.
|
|
74
|
+
*
|
|
75
|
+
* Produces color-coded output like:
|
|
76
|
+
* [browser:error] Uncaught TypeError: x is not a function
|
|
77
|
+
* at App (app.tsx:10:5)
|
|
78
|
+
* [browser:warn] Deprecation warning (app/page.tsx:42:12)
|
|
79
|
+
*/
|
|
80
|
+
export function formatBrowserLog(payload: BrowserLogPayload): string {
|
|
81
|
+
const { level, message, stack, source } = payload;
|
|
82
|
+
|
|
83
|
+
// Color-coded prefix
|
|
84
|
+
const color = level === 'error' ? COLORS.red : level === 'warn' ? COLORS.yellow : COLORS.blue;
|
|
85
|
+
const prefix = `${color}[browser:${level}]${COLORS.reset}`;
|
|
86
|
+
|
|
87
|
+
// Source suffix
|
|
88
|
+
const sourceSuffix = source ? ` ${COLORS.dim}(${source})${COLORS.reset}` : '';
|
|
89
|
+
|
|
90
|
+
let output = `${prefix} ${message}${sourceSuffix}`;
|
|
91
|
+
|
|
92
|
+
// Append stack trace indented
|
|
93
|
+
if (stack) {
|
|
94
|
+
const indented = stack
|
|
95
|
+
.split('\n')
|
|
96
|
+
.map((line) => ` ${COLORS.dim}${line}${COLORS.reset}`)
|
|
97
|
+
.join('\n');
|
|
98
|
+
output += `\n${indented}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return output;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ─── Level Filtering ─────────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Check if a log at `level` should be forwarded given the configured threshold.
|
|
108
|
+
*
|
|
109
|
+
* The threshold acts as a minimum severity:
|
|
110
|
+
* - 'error' → only errors
|
|
111
|
+
* - 'warn' → errors + warnings
|
|
112
|
+
* - 'info' → errors + warnings + info
|
|
113
|
+
* - 'none' → nothing
|
|
114
|
+
*/
|
|
115
|
+
export function shouldForwardLevel(
|
|
116
|
+
level: BrowserLogLevel,
|
|
117
|
+
threshold: BrowserLogLevel | 'none'
|
|
118
|
+
): boolean {
|
|
119
|
+
if (threshold === 'none') return false;
|
|
120
|
+
return LEVEL_SEVERITY[level] >= LEVEL_SEVERITY[threshold];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ─── Truncation ──────────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Truncate a message to `maxBytes` to avoid flooding the terminal.
|
|
127
|
+
* Appends a suffix indicating how many bytes were dropped.
|
|
128
|
+
*/
|
|
129
|
+
export function truncateMessage(message: string, maxBytes: number): string {
|
|
130
|
+
if (message.length <= maxBytes) return message;
|
|
131
|
+
|
|
132
|
+
const truncated = message.slice(0, maxBytes);
|
|
133
|
+
const droppedBytes = message.length - maxBytes;
|
|
134
|
+
return `${truncated}… [truncated ${droppedBytes} bytes]`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ─── Client Injection Script ─────────────────────────────────────────────
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Generate the inline script injected into the browser in dev mode.
|
|
141
|
+
*
|
|
142
|
+
* This script:
|
|
143
|
+
* 1. Saves references to the original console methods
|
|
144
|
+
* 2. Wraps `console.error`, `console.warn`, `console.info`
|
|
145
|
+
* 3. Calls the original first (browser devtools still work)
|
|
146
|
+
* 4. Serializes and forwards via `import.meta.hot.send()`
|
|
147
|
+
* 5. Truncates messages to MAX_MESSAGE_BYTES
|
|
148
|
+
*
|
|
149
|
+
* The script is minimal and self-contained — no imports, no dependencies.
|
|
150
|
+
*/
|
|
151
|
+
export function generateClientScript(threshold: BrowserLogLevel | 'none'): string {
|
|
152
|
+
if (threshold === 'none') return '';
|
|
153
|
+
|
|
154
|
+
// Only intercept levels that meet the threshold
|
|
155
|
+
const levels: BrowserLogLevel[] = ['error', 'warn', 'info'].filter((l) =>
|
|
156
|
+
shouldForwardLevel(l as BrowserLogLevel, threshold)
|
|
157
|
+
) as BrowserLogLevel[];
|
|
158
|
+
|
|
159
|
+
if (levels.length === 0) return '';
|
|
160
|
+
|
|
161
|
+
return `
|
|
162
|
+
(function() {
|
|
163
|
+
if (!import.meta.hot) return;
|
|
164
|
+
var MAX_BYTES = ${MAX_MESSAGE_BYTES};
|
|
165
|
+
var levels = ${JSON.stringify(levels)};
|
|
166
|
+
var originals = {};
|
|
167
|
+
|
|
168
|
+
function serialize(arg) {
|
|
169
|
+
if (arg === null) return 'null';
|
|
170
|
+
if (arg === undefined) return 'undefined';
|
|
171
|
+
if (arg instanceof Error) return arg.stack || arg.message || String(arg);
|
|
172
|
+
if (typeof arg === 'object') {
|
|
173
|
+
try { return JSON.stringify(arg); } catch(e) { return String(arg); }
|
|
174
|
+
}
|
|
175
|
+
return String(arg);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function truncate(s) {
|
|
179
|
+
if (s.length <= MAX_BYTES) return s;
|
|
180
|
+
return s.slice(0, MAX_BYTES) + '... [truncated ' + (s.length - MAX_BYTES) + ' bytes]';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
levels.forEach(function(level) {
|
|
184
|
+
originals[level] = console[level];
|
|
185
|
+
console[level] = function() {
|
|
186
|
+
originals[level].apply(console, arguments);
|
|
187
|
+
try {
|
|
188
|
+
var args = Array.prototype.slice.call(arguments);
|
|
189
|
+
var firstArg = args[0];
|
|
190
|
+
var stack = null;
|
|
191
|
+
var source = null;
|
|
192
|
+
|
|
193
|
+
if (firstArg instanceof Error) {
|
|
194
|
+
stack = firstArg.stack || null;
|
|
195
|
+
source = null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
var message = args.map(serialize).join(' ');
|
|
199
|
+
message = truncate(message);
|
|
200
|
+
|
|
201
|
+
import.meta.hot.send('${HMR_EVENT}', {
|
|
202
|
+
level: level,
|
|
203
|
+
message: message,
|
|
204
|
+
stack: stack,
|
|
205
|
+
source: source,
|
|
206
|
+
timestamp: Date.now()
|
|
207
|
+
});
|
|
208
|
+
} catch(e) {
|
|
209
|
+
// Never let log forwarding break the page
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
})();
|
|
214
|
+
`.trim();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ─── Plugin ──────────────────────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Create the timber-dev-browser-logs Vite plugin.
|
|
221
|
+
*
|
|
222
|
+
* - `configureServer`: Listens for HMR messages and prints them to the terminal
|
|
223
|
+
* - `transformIndexHtml`: Injects the client-side interception script
|
|
224
|
+
*
|
|
225
|
+
* Only active during `vite dev` (apply: 'serve').
|
|
226
|
+
*/
|
|
227
|
+
export function timberDevBrowserLogs(ctx: PluginContext): Plugin {
|
|
228
|
+
return {
|
|
229
|
+
name: 'timber-dev-browser-logs',
|
|
230
|
+
apply: 'serve',
|
|
231
|
+
|
|
232
|
+
configureServer(server: ViteDevServer) {
|
|
233
|
+
const threshold = ctx.config.devBrowserLogs ?? 'warn';
|
|
234
|
+
if (threshold === 'none') {
|
|
235
|
+
// Clear any stale script from a prior server instance (e.g. HMR reconfigure)
|
|
236
|
+
delete (globalThis as Record<string, unknown>).__timber_dev_browser_log_script;
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Register the client injection script on globalThis so the RSC entry
|
|
241
|
+
// can include it in headHtml for all Timber route responses.
|
|
242
|
+
// transformIndexHtml only runs for Vite's index.html fallback, not
|
|
243
|
+
// for responses served by createTimberMiddleware (TIM-575).
|
|
244
|
+
const script = generateClientScript(threshold);
|
|
245
|
+
if (script) {
|
|
246
|
+
(globalThis as Record<string, unknown>).__timber_dev_browser_log_script =
|
|
247
|
+
`<script type="module">${script}</script>`;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Listen for browser log messages via HMR WebSocket
|
|
251
|
+
server.hot.on(HMR_EVENT, (payload: BrowserLogPayload) => {
|
|
252
|
+
try {
|
|
253
|
+
// Validate level
|
|
254
|
+
if (!shouldForwardLevel(payload.level, threshold)) return;
|
|
255
|
+
|
|
256
|
+
// Truncate server-side too (defense in depth)
|
|
257
|
+
payload.message = truncateMessage(payload.message, MAX_MESSAGE_BYTES);
|
|
258
|
+
|
|
259
|
+
const formatted = formatBrowserLog(payload);
|
|
260
|
+
|
|
261
|
+
// Use the correct console method for the log level
|
|
262
|
+
if (payload.level === 'error') {
|
|
263
|
+
process.stderr.write(formatted + '\n');
|
|
264
|
+
} else {
|
|
265
|
+
process.stdout.write(formatted + '\n');
|
|
266
|
+
}
|
|
267
|
+
} catch {
|
|
268
|
+
// Never let log forwarding crash the server
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
transformIndexHtml() {
|
|
274
|
+
const threshold = ctx.config.devBrowserLogs ?? 'warn';
|
|
275
|
+
const script = generateClientScript(threshold);
|
|
276
|
+
if (!script) return [];
|
|
277
|
+
|
|
278
|
+
return [
|
|
279
|
+
{
|
|
280
|
+
tag: 'script',
|
|
281
|
+
attrs: { type: 'module' },
|
|
282
|
+
children: script,
|
|
283
|
+
injectTo: 'head' as const,
|
|
284
|
+
},
|
|
285
|
+
];
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
}
|
|
@@ -180,6 +180,63 @@ export function formatTerminalError(error: Error, phase: ErrorPhase, projectRoot
|
|
|
180
180
|
return lines.join('\n');
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
// ─── RSC Debug Context ──────────────────────────────────────────────────────
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Component info extracted from the RSC debug channel.
|
|
187
|
+
* Contains only names, environments, and stack frames — never source code.
|
|
188
|
+
*/
|
|
189
|
+
export interface RscDebugComponentInfo {
|
|
190
|
+
name: string;
|
|
191
|
+
env: string | null;
|
|
192
|
+
stack: unknown[] | null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Format RSC debug component info into a readable string for the overlay.
|
|
197
|
+
*
|
|
198
|
+
* Renders the server component tree that was active when an error occurred,
|
|
199
|
+
* including component names and source locations from stack frames. This
|
|
200
|
+
* gives developers visibility into which server components were rendering
|
|
201
|
+
* without exposing source code.
|
|
202
|
+
*
|
|
203
|
+
* Returns an empty string if no components are provided.
|
|
204
|
+
*/
|
|
205
|
+
export function formatRscDebugContext(components: RscDebugComponentInfo[]): string {
|
|
206
|
+
if (!components || components.length === 0) return '';
|
|
207
|
+
|
|
208
|
+
// Deduplicate by name — the debug channel may emit the same component
|
|
209
|
+
// multiple times (e.g., when re-rendered or when multiple instances exist).
|
|
210
|
+
const seen = new Set<string>();
|
|
211
|
+
const unique: RscDebugComponentInfo[] = [];
|
|
212
|
+
for (const c of components) {
|
|
213
|
+
if (!seen.has(c.name)) {
|
|
214
|
+
seen.add(c.name);
|
|
215
|
+
unique.push(c);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const lines: string[] = ['Server Component Tree:'];
|
|
220
|
+
for (let i = 0; i < unique.length; i++) {
|
|
221
|
+
const c = unique[i]!;
|
|
222
|
+
const indent = ' '.repeat(i + 1);
|
|
223
|
+
const envLabel = c.env ? ` [${c.env}]` : '';
|
|
224
|
+
|
|
225
|
+
// Extract file location from stack frames if available
|
|
226
|
+
let locStr = '';
|
|
227
|
+
if (c.stack && c.stack.length > 0) {
|
|
228
|
+
const frame = c.stack[0] as [string, string, number, number] | undefined;
|
|
229
|
+
if (Array.isArray(frame) && frame.length >= 3) {
|
|
230
|
+
locStr = ` (${frame[1]}:${frame[2]})`;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
lines.push(`${indent}${c.name}${envLabel}${locStr}`);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return lines.join('\n');
|
|
238
|
+
}
|
|
239
|
+
|
|
183
240
|
// ─── Overlay Integration ────────────────────────────────────────────────────
|
|
184
241
|
|
|
185
242
|
/**
|
|
@@ -188,13 +245,19 @@ export function formatTerminalError(error: Error, phase: ErrorPhase, projectRoot
|
|
|
188
245
|
* Uses `server.ssrFixStacktrace()` to map stack traces back to source,
|
|
189
246
|
* then sends the error via `server.hot.send()` for the browser overlay.
|
|
190
247
|
*
|
|
248
|
+
* When `rscDebugComponents` is provided (dev mode only), the server
|
|
249
|
+
* component tree context is appended to the error message. This helps
|
|
250
|
+
* developers identify which server component caused the error without
|
|
251
|
+
* exposing source code.
|
|
252
|
+
*
|
|
191
253
|
* The dev server remains running — errors are handled, not fatal.
|
|
192
254
|
*/
|
|
193
255
|
export function sendErrorToOverlay(
|
|
194
256
|
server: ViteDevServer,
|
|
195
257
|
error: Error,
|
|
196
258
|
phase: ErrorPhase,
|
|
197
|
-
projectRoot: string
|
|
259
|
+
projectRoot: string,
|
|
260
|
+
rscDebugComponents?: RscDebugComponentInfo[]
|
|
198
261
|
): void {
|
|
199
262
|
// Fix stack trace to use source-mapped positions
|
|
200
263
|
server.ssrFixStacktrace(error);
|
|
@@ -212,6 +275,12 @@ export function sendErrorToOverlay(
|
|
|
212
275
|
message = `${error.message}\n\nComponent Stack:\n${componentStack.trim()}`;
|
|
213
276
|
}
|
|
214
277
|
|
|
278
|
+
// Append RSC debug context if available (dev mode only)
|
|
279
|
+
const debugContext = formatRscDebugContext(rscDebugComponents ?? []);
|
|
280
|
+
if (debugContext) {
|
|
281
|
+
message = `${message}\n\n${debugContext}`;
|
|
282
|
+
}
|
|
283
|
+
|
|
215
284
|
// Send to browser via Vite's error overlay protocol
|
|
216
285
|
try {
|
|
217
286
|
server.hot.send({
|
package/src/plugins/dev-logs.ts
CHANGED
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
import type { Plugin, ViteDevServer, DevEnvironment } from 'vite';
|
|
16
16
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
17
17
|
import { join } from 'node:path';
|
|
18
|
-
import type { PluginContext } from '
|
|
19
|
-
import { setViteServer } from '
|
|
18
|
+
import type { PluginContext } from '../index.js';
|
|
19
|
+
import { setViteServer } from '../server/dev-warnings.js';
|
|
20
20
|
import { sendErrorToOverlay, classifyErrorPhase, parseFirstAppFrame } from './dev-error-overlay.js';
|
|
21
|
-
import { compressResponse } from '
|
|
21
|
+
import { compressResponse } from '../server/compress.js';
|
|
22
22
|
|
|
23
23
|
// ─── Constants ────────────────────────────────────────────────────────────
|
|
24
24
|
|
|
@@ -161,12 +161,26 @@ function createTimberMiddleware(server: ViteDevServer, projectRoot: string) {
|
|
|
161
161
|
|
|
162
162
|
// Wire pipeline errors into the browser error overlay.
|
|
163
163
|
// setDevPipelineErrorHandler is only defined in dev (rsc-entry.ts exports it).
|
|
164
|
+
// The handler receives optional RSC debug component data (component names,
|
|
165
|
+
// environments, stack frames) from the Flight debug channel for render errors.
|
|
164
166
|
const setHandler = rscModule.setDevPipelineErrorHandler as
|
|
165
|
-
| ((
|
|
167
|
+
| ((
|
|
168
|
+
fn: (
|
|
169
|
+
error: Error,
|
|
170
|
+
phase: string,
|
|
171
|
+
debugComponents?: Array<{ name: string; env: string | null; stack: unknown[] | null }>
|
|
172
|
+
) => void
|
|
173
|
+
) => void)
|
|
166
174
|
| undefined;
|
|
167
175
|
if (typeof setHandler === 'function') {
|
|
168
|
-
setHandler((error) => {
|
|
169
|
-
sendErrorToOverlay(
|
|
176
|
+
setHandler((error, _phase, debugComponents) => {
|
|
177
|
+
sendErrorToOverlay(
|
|
178
|
+
server,
|
|
179
|
+
error,
|
|
180
|
+
classifyErrorPhase(error, projectRoot),
|
|
181
|
+
projectRoot,
|
|
182
|
+
debugComponents
|
|
183
|
+
);
|
|
170
184
|
});
|
|
171
185
|
}
|
|
172
186
|
} catch (error) {
|
|
@@ -191,8 +205,20 @@ function createTimberMiddleware(server: ViteDevServer, projectRoot: string) {
|
|
|
191
205
|
// Convert Node IncomingMessage → Web Request
|
|
192
206
|
const webRequest = toWebRequest(req);
|
|
193
207
|
|
|
194
|
-
//
|
|
195
|
-
|
|
208
|
+
// Check for a platform-specific request wrapper (e.g., Cloudflare
|
|
209
|
+
// dev bindings). The cloudflareDevBindings() plugin stores a wrapper
|
|
210
|
+
// function on the server instance using a well-known Symbol. The
|
|
211
|
+
// wrapper runs the handler inside an ALS context so platform APIs
|
|
212
|
+
// like getCloudflareBindings() work during dev.
|
|
213
|
+
// See design/35-cloudflare-primitives.md §"Dev Experience".
|
|
214
|
+
const wrapper = (server as any)[Symbol.for('timber:dev-request-wrapper')] as
|
|
215
|
+
| (<T>(fn: () => T) => T)
|
|
216
|
+
| undefined;
|
|
217
|
+
|
|
218
|
+
// Run the full pipeline (wrapped if a platform dev plugin is active)
|
|
219
|
+
const webResponse = wrapper
|
|
220
|
+
? await wrapper(() => handler(webRequest))
|
|
221
|
+
: await handler(webRequest);
|
|
196
222
|
|
|
197
223
|
// Compress the response if the client supports it.
|
|
198
224
|
// In dev mode, compression is always enabled for parity with production.
|
|
@@ -317,6 +343,17 @@ async function sendWebResponse(nodeRes: ServerResponse, webResponse: Response):
|
|
|
317
343
|
nodeRes.flushHeaders();
|
|
318
344
|
|
|
319
345
|
const reader = webResponse.body.getReader();
|
|
346
|
+
|
|
347
|
+
// Cancel the reader when the client disconnects. This causes any pending
|
|
348
|
+
// reader.read() to reject, breaking the pump loop. Critical for SSE and
|
|
349
|
+
// other infinite streams — without this, disconnected clients leak readers.
|
|
350
|
+
let clientDisconnected = false;
|
|
351
|
+
const onClose = () => {
|
|
352
|
+
clientDisconnected = true;
|
|
353
|
+
reader.cancel('Client disconnected').catch(() => {});
|
|
354
|
+
};
|
|
355
|
+
nodeRes.on('close', onClose);
|
|
356
|
+
|
|
320
357
|
try {
|
|
321
358
|
while (true) {
|
|
322
359
|
const { done, value } = await reader.read();
|
|
@@ -325,9 +362,18 @@ async function sendWebResponse(nodeRes: ServerResponse, webResponse: Response):
|
|
|
325
362
|
// don't need back-pressure here — just keep pushing chunks.
|
|
326
363
|
nodeRes.write(value);
|
|
327
364
|
}
|
|
365
|
+
} catch (err) {
|
|
366
|
+
// reader.cancel() from the close handler causes read() to reject.
|
|
367
|
+
// This is expected on client disconnect — not an error.
|
|
368
|
+
if (!clientDisconnected) {
|
|
369
|
+
throw err;
|
|
370
|
+
}
|
|
328
371
|
} finally {
|
|
372
|
+
nodeRes.off('close', onClose);
|
|
329
373
|
reader.releaseLock();
|
|
330
|
-
nodeRes.
|
|
374
|
+
if (!nodeRes.writableEnded) {
|
|
375
|
+
nodeRes.end();
|
|
376
|
+
}
|
|
331
377
|
}
|
|
332
378
|
}
|
|
333
379
|
|