@timber-js/app 0.2.0-alpha.6 → 0.2.0-alpha.60
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-Ba7URUIn.js} +1 -1
- package/dist/_chunks/als-registry-Ba7URUIn.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-D5STJpIr.js +121 -0
- package/dist/_chunks/define-D5STJpIr.js.map +1 -0
- package/dist/_chunks/define-TK8C1M3x.js +279 -0
- package/dist/_chunks/define-TK8C1M3x.js.map +1 -0
- package/dist/_chunks/define-cookie-DtAavax4.js +93 -0
- package/dist/_chunks/define-cookie-DtAavax4.js.map +1 -0
- package/dist/_chunks/error-boundary-DpZJBCqh.js +211 -0
- package/dist/_chunks/error-boundary-DpZJBCqh.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → format-cX7wzEp2.js} +2 -2
- package/dist/_chunks/{format-DviM89f0.js.map → format-cX7wzEp2.js.map} +1 -1
- package/dist/_chunks/{interception-BOoWmLUA.js → interception-Cey5DCGr.js} +129 -77
- package/dist/_chunks/interception-Cey5DCGr.js.map +1 -0
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-BU684ls2.js} +1 -1
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-BU684ls2.js.map} +1 -1
- package/dist/_chunks/{request-context-DIkVh_jG.js → request-context-0wfZsnhh.js} +97 -69
- package/dist/_chunks/request-context-0wfZsnhh.js.map +1 -0
- package/dist/_chunks/segment-context-CyaM1mrD.js +72 -0
- package/dist/_chunks/segment-context-CyaM1mrD.js.map +1 -0
- package/dist/_chunks/stale-reload-DKN3aXxR.js +61 -0
- package/dist/_chunks/stale-reload-DKN3aXxR.js.map +1 -0
- package/dist/_chunks/{tracing-Cwn7697K.js → tracing-VYETCQsg.js} +17 -3
- package/dist/_chunks/{tracing-Cwn7697K.js.map → tracing-VYETCQsg.js.map} +1 -1
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-wEXY2JQB.js} +1 -1
- package/dist/_chunks/use-query-states-wEXY2JQB.js.map +1 -0
- package/dist/_chunks/wrappers-BaG1bnM3.js +63 -0
- package/dist/_chunks/wrappers-BaG1bnM3.js.map +1 -0
- 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/fast-hash.d.ts +22 -0
- package/dist/cache/fast-hash.d.ts.map +1 -0
- package/dist/cache/index.d.ts +5 -2
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +90 -20
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/register-cached-function.d.ts.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 +10 -1
- 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/index.d.ts +3 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +433 -252
- 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 +23 -9
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-context.d.ts +2 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/router.d.ts +25 -3
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +36 -2
- 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/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +1 -1
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/transition-root.d.ts +1 -1
- package/dist/client/transition-root.d.ts.map +1 -1
- package/dist/client/use-params.d.ts +3 -3
- 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 +21 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/cookies/define-cookie.d.ts +34 -13
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -83
- package/dist/fonts/css.d.ts +1 -0
- package/dist/fonts/css.d.ts.map +1 -1
- package/dist/index.d.ts +127 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +663 -242
- package/dist/index.js.map +1 -1
- package/dist/params/define.d.ts +100 -0
- package/dist/params/define.d.ts.map +1 -0
- package/dist/params/index.d.ts +8 -0
- package/dist/params/index.d.ts.map +1 -0
- package/dist/params/index.js +4 -0
- 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 +9 -2
- 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.js +1 -1
- package/dist/routing/scanner.d.ts.map +1 -1
- 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/search-params/codecs.d.ts +1 -1
- package/dist/search-params/define.d.ts +159 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -5
- 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/server/access-gate.d.ts +4 -0
- package/dist/server/access-gate.d.ts.map +1 -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 +1 -1
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +25 -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-renderer.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 +4 -0
- 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 +4 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1975 -1648
- 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/node-stream-transforms.d.ts +113 -0
- package/dist/server/node-stream-transforms.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.d.ts +20 -6
- 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 +65 -38
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +7 -0
- 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/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 +20 -13
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +1 -3
- 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/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/state-machine.d.ts +80 -0
- package/dist/utils/state-machine.d.ts.map +1 -0
- package/package.json +17 -17
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +58 -9
- package/src/cache/fast-hash.ts +34 -0
- package/src/cache/index.ts +5 -2
- package/src/cache/register-cached-function.ts +7 -3
- 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 +139 -99
- package/src/client/error-boundary.tsx +18 -1
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +2 -2
- package/src/client/index.ts +10 -1
- package/src/client/link-pending-store.ts +136 -0
- package/src/client/link.tsx +137 -22
- package/src/client/navigation-context.ts +6 -5
- package/src/client/router.ts +117 -60
- package/src/client/rsc-fetch.ts +88 -2
- 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/stale-reload.ts +56 -6
- package/src/client/top-loader.tsx +10 -9
- package/src/client/transition-root.tsx +20 -2
- package/src/client/use-params.ts +4 -4
- package/src/client/use-query-states.ts +2 -2
- package/src/codec.ts +21 -0
- package/src/cookies/define-cookie.ts +71 -20
- package/src/fonts/css.ts +2 -1
- package/src/index.ts +297 -85
- package/src/params/define.ts +320 -0
- package/src/params/index.ts +28 -0
- 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/cache-transform.ts +1 -1
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-browser-logs.ts +274 -0
- package/src/plugins/dev-error-overlay.ts +70 -1
- package/src/plugins/dev-logs.ts +1 -1
- package/src/plugins/dev-server.ts +41 -7
- package/src/plugins/entries.ts +6 -8
- package/src/plugins/fonts.ts +102 -55
- 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 +69 -31
- package/src/plugins/static-build.ts +10 -6
- package/src/routing/codegen.ts +109 -88
- package/src/routing/scanner.ts +86 -7
- 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 +1 -1
- package/src/search-params/define.ts +518 -0
- package/src/search-params/index.ts +12 -18
- package/src/search-params/registry.ts +1 -1
- package/src/search-params/wrappers.ts +85 -0
- package/src/server/access-gate.tsx +40 -9
- package/src/server/action-client.ts +8 -2
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +20 -3
- package/src/server/actions.ts +1 -1
- package/src/server/als-registry.ts +25 -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-renderer.ts +5 -3
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +58 -15
- package/src/server/fallback-error.ts +10 -7
- 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 -4
- package/src/server/logger.ts +44 -36
- package/src/server/node-stream-transforms.ts +509 -0
- package/src/server/pipeline-interception.ts +1 -1
- package/src/server/pipeline.ts +139 -41
- package/src/server/primitives.ts +47 -5
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +125 -119
- package/src/server/route-element-builder.ts +107 -115
- package/src/server/route-handler.ts +2 -1
- package/src/server/route-matcher.ts +9 -2
- package/src/server/rsc-entry/api-handler.ts +8 -8
- package/src/server/rsc-entry/error-renderer.ts +277 -81
- package/src/server/rsc-entry/helpers.ts +134 -5
- package/src/server/rsc-entry/index.ts +165 -76
- package/src/server/rsc-entry/rsc-payload.ts +91 -18
- package/src/server/rsc-entry/rsc-stream.ts +74 -18
- package/src/server/rsc-entry/ssr-bridge.ts +2 -2
- package/src/server/rsc-entry/ssr-renderer.ts +141 -34
- package/src/server/slot-resolver.ts +231 -220
- 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 +209 -0
- package/src/server/tracing.ts +23 -0
- package/src/server/tree-builder.ts +92 -58
- package/src/server/types.ts +1 -3
- 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/navigation-client.ts +1 -1
- package/src/shims/navigation.ts +2 -1
- 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/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/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/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/cookies/index.js.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/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/client/link-status-provider.tsx +0 -30
- 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
package/src/plugins/fonts.ts
CHANGED
|
@@ -17,26 +17,41 @@
|
|
|
17
17
|
import type { Plugin, ViteDevServer } from 'vite';
|
|
18
18
|
import { readFileSync, existsSync } from 'node:fs';
|
|
19
19
|
import { resolve, normalize } from 'node:path';
|
|
20
|
-
import type { PluginContext } from '
|
|
21
|
-
import type { ExtractedFont, GoogleFontConfig } from '
|
|
22
|
-
import type { ManifestFontEntry } from '
|
|
23
|
-
import { generateVariableClass, generateFontFamilyClass, generateFontFaces } from '
|
|
24
|
-
import { generateFallbackCss, buildFontStack } from '
|
|
25
|
-
import { processLocalFont, generateLocalFontFaces } from '
|
|
26
|
-
import { inferFontFormat } from '
|
|
27
|
-
import { downloadAndCacheFonts, type CachedFont } from '
|
|
20
|
+
import type { PluginContext } from '../index.js';
|
|
21
|
+
import type { ExtractedFont, GoogleFontConfig } from '../fonts/types.js';
|
|
22
|
+
import type { ManifestFontEntry } from '../server/build-manifest.js';
|
|
23
|
+
import { generateVariableClass, generateFontFamilyClass, generateFontFaces } from '../fonts/css.js';
|
|
24
|
+
import { generateFallbackCss, buildFontStack } from '../fonts/fallbacks.js';
|
|
25
|
+
import { processLocalFont, generateLocalFontFaces } from '../fonts/local.js';
|
|
26
|
+
import { inferFontFormat } from '../fonts/local.js';
|
|
27
|
+
import { downloadAndCacheFonts, type CachedFont } from '../fonts/google.js';
|
|
28
28
|
import {
|
|
29
29
|
extractFontConfigAst,
|
|
30
30
|
extractLocalFontConfigAst,
|
|
31
31
|
detectDynamicFontCallAst,
|
|
32
|
-
} from '
|
|
32
|
+
} from '../fonts/ast.js';
|
|
33
33
|
|
|
34
34
|
const VIRTUAL_GOOGLE = '@timber/fonts/google';
|
|
35
35
|
const VIRTUAL_LOCAL = '@timber/fonts/local';
|
|
36
|
-
const VIRTUAL_FONT_CSS = 'virtual:timber-fonts.css';
|
|
37
36
|
const RESOLVED_GOOGLE = '\0@timber/fonts/google';
|
|
38
37
|
const RESOLVED_LOCAL = '\0@timber/fonts/local';
|
|
39
|
-
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Virtual side-effect module that registers font CSS on globalThis.
|
|
41
|
+
*
|
|
42
|
+
* When a file calls localFont() or a Google font function, the transform
|
|
43
|
+
* hook injects `import 'virtual:timber-font-css-register'` into that file.
|
|
44
|
+
* This virtual module sets `globalThis.__timber_font_css` with the combined
|
|
45
|
+
* @font-face CSS. The RSC entry reads it at render time to inline a <style> tag.
|
|
46
|
+
*
|
|
47
|
+
* This approach avoids timing issues because:
|
|
48
|
+
* 1. The font file is in the RSC module graph (imported by layout.tsx)
|
|
49
|
+
* 2. The side-effect import is added to the font file during transform
|
|
50
|
+
* 3. When layout.tsx is loaded, fonts.ts runs → side-effect module runs → globalThis is set
|
|
51
|
+
* 4. RSC entry renders → reads globalThis → inlines <style>
|
|
52
|
+
*/
|
|
53
|
+
const VIRTUAL_FONT_CSS_REGISTER = 'virtual:timber-font-css-register';
|
|
54
|
+
const RESOLVED_FONT_CSS_REGISTER = '\0virtual:timber-font-css-register';
|
|
40
55
|
|
|
41
56
|
/**
|
|
42
57
|
* Registry of fonts extracted during transform.
|
|
@@ -246,6 +261,33 @@ function generateLocalVirtualModule(): string {
|
|
|
246
261
|
].join('\n');
|
|
247
262
|
}
|
|
248
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Generate CSS for a single extracted font.
|
|
266
|
+
*
|
|
267
|
+
* Includes @font-face rules (for local fonts), fallback @font-face,
|
|
268
|
+
* and the scoped class rule.
|
|
269
|
+
*/
|
|
270
|
+
export function generateFontCss(font: ExtractedFont): string {
|
|
271
|
+
const cssParts: string[] = [];
|
|
272
|
+
|
|
273
|
+
if (font.provider === 'local' && font.localSources) {
|
|
274
|
+
const faces = generateLocalFontFaces(font.family, font.localSources, font.display);
|
|
275
|
+
const faceCss = generateFontFaces(faces);
|
|
276
|
+
if (faceCss) cssParts.push(faceCss);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const fallbackCss = generateFallbackCss(font.family);
|
|
280
|
+
if (fallbackCss) cssParts.push(fallbackCss);
|
|
281
|
+
|
|
282
|
+
if (font.variable) {
|
|
283
|
+
cssParts.push(generateVariableClass(font.className, font.variable, font.fontFamily));
|
|
284
|
+
} else {
|
|
285
|
+
cssParts.push(generateFontFamilyClass(font.className, font.fontFamily));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return cssParts.join('\n\n');
|
|
289
|
+
}
|
|
290
|
+
|
|
249
291
|
/**
|
|
250
292
|
* Generate the CSS output for all extracted fonts.
|
|
251
293
|
*
|
|
@@ -254,27 +296,9 @@ function generateLocalVirtualModule(): string {
|
|
|
254
296
|
*/
|
|
255
297
|
export function generateAllFontCss(registry: FontRegistry): string {
|
|
256
298
|
const cssParts: string[] = [];
|
|
257
|
-
|
|
258
299
|
for (const font of registry.values()) {
|
|
259
|
-
|
|
260
|
-
if (font.provider === 'local' && font.localSources) {
|
|
261
|
-
const faces = generateLocalFontFaces(font.family, font.localSources, font.display);
|
|
262
|
-
const faceCss = generateFontFaces(faces);
|
|
263
|
-
if (faceCss) cssParts.push(faceCss);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Generate fallback @font-face if metrics are available
|
|
267
|
-
const fallbackCss = generateFallbackCss(font.family);
|
|
268
|
-
if (fallbackCss) cssParts.push(fallbackCss);
|
|
269
|
-
|
|
270
|
-
// Generate scoped class
|
|
271
|
-
if (font.variable) {
|
|
272
|
-
cssParts.push(generateVariableClass(font.className, font.variable, font.fontFamily));
|
|
273
|
-
} else {
|
|
274
|
-
cssParts.push(generateFontFamilyClass(font.className, font.fontFamily));
|
|
275
|
-
}
|
|
300
|
+
cssParts.push(generateFontCss(font));
|
|
276
301
|
}
|
|
277
|
-
|
|
278
302
|
return cssParts.join('\n\n');
|
|
279
303
|
}
|
|
280
304
|
|
|
@@ -371,34 +395,61 @@ export function timberFonts(ctx: PluginContext): Plugin {
|
|
|
371
395
|
name: 'timber-fonts',
|
|
372
396
|
|
|
373
397
|
/**
|
|
374
|
-
* Resolve `@timber/fonts/google`, `@timber/fonts/local`,
|
|
375
|
-
* virtual
|
|
398
|
+
* Resolve `@timber/fonts/google`, `@timber/fonts/local`,
|
|
399
|
+
* and `virtual:timber-font-css` virtual modules.
|
|
400
|
+
*
|
|
401
|
+
* Handles \0 prefix and root prefix stripping for RSC/SSR
|
|
402
|
+
* environments where the RSC plugin re-imports virtual modules
|
|
403
|
+
* with additional prefixes.
|
|
376
404
|
*/
|
|
377
405
|
resolveId(id: string) {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
406
|
+
// Strip \0 prefix (RSC plugin re-imports)
|
|
407
|
+
let cleanId = id.startsWith('\0') ? id.slice(1) : id;
|
|
408
|
+
// Strip root prefix (SSR build entries)
|
|
409
|
+
if (cleanId.startsWith(ctx.root)) {
|
|
410
|
+
const stripped = cleanId.slice(ctx.root.length);
|
|
411
|
+
if (stripped.startsWith('/') || stripped.startsWith('\\')) {
|
|
412
|
+
cleanId = stripped.slice(1);
|
|
413
|
+
} else {
|
|
414
|
+
cleanId = stripped;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (cleanId === VIRTUAL_GOOGLE) return RESOLVED_GOOGLE;
|
|
419
|
+
if (cleanId === VIRTUAL_LOCAL) return RESOLVED_LOCAL;
|
|
420
|
+
if (cleanId === VIRTUAL_FONT_CSS_REGISTER) return RESOLVED_FONT_CSS_REGISTER;
|
|
381
421
|
return null;
|
|
382
422
|
},
|
|
383
423
|
|
|
384
424
|
/**
|
|
385
425
|
* Return generated source for font virtual modules.
|
|
386
426
|
*
|
|
387
|
-
*
|
|
388
|
-
*
|
|
427
|
+
* `virtual:timber-font-css` exports the combined @font-face CSS
|
|
428
|
+
* as a string. The RSC entry imports it and inlines a <style> tag.
|
|
429
|
+
* Because this is loaded lazily (on first request), the font
|
|
430
|
+
* registry is always populated by the time it's needed.
|
|
389
431
|
*/
|
|
390
432
|
load(id: string) {
|
|
391
433
|
if (id === RESOLVED_GOOGLE) return generateGoogleVirtualModule(registry);
|
|
392
434
|
if (id === RESOLVED_LOCAL) return generateLocalVirtualModule();
|
|
393
|
-
|
|
435
|
+
|
|
436
|
+
if (id === RESOLVED_FONT_CSS_REGISTER) {
|
|
437
|
+
const css = generateAllFontCss(registry);
|
|
438
|
+
// Side-effect module: sets font CSS on globalThis for the RSC entry to read.
|
|
439
|
+
return `globalThis.__timber_font_css = ${JSON.stringify(css)};`;
|
|
440
|
+
}
|
|
394
441
|
return null;
|
|
395
442
|
},
|
|
396
443
|
|
|
397
444
|
/**
|
|
398
|
-
* Serve local font files in dev mode under `/_timber/fonts/`.
|
|
445
|
+
* Serve local font files and font CSS in dev mode under `/_timber/fonts/`.
|
|
446
|
+
*
|
|
447
|
+
* Serves:
|
|
448
|
+
* - `/_timber/fonts/fonts.css` — combined @font-face + scoped class CSS
|
|
449
|
+
* - `/_timber/fonts/<filename>` — individual font files from the registry
|
|
399
450
|
*
|
|
400
|
-
* Only files
|
|
401
|
-
*
|
|
451
|
+
* Only files registered in the font registry are served.
|
|
452
|
+
* Paths are validated to prevent directory traversal.
|
|
402
453
|
*/
|
|
403
454
|
configureServer(server: ViteDevServer) {
|
|
404
455
|
server.middlewares.use((req, res, next) => {
|
|
@@ -413,6 +464,9 @@ export function timberFonts(ctx: PluginContext): Plugin {
|
|
|
413
464
|
return;
|
|
414
465
|
}
|
|
415
466
|
|
|
467
|
+
// Font CSS is now injected via Vite's CSS pipeline (virtual:timber-font-css modules).
|
|
468
|
+
// This middleware only serves font binary files (woff2, etc.).
|
|
469
|
+
|
|
416
470
|
// Find the matching font file in the registry
|
|
417
471
|
for (const font of registry.values()) {
|
|
418
472
|
if (font.provider !== 'local' || !font.localSources) continue;
|
|
@@ -420,7 +474,6 @@ export function timberFonts(ctx: PluginContext): Plugin {
|
|
|
420
474
|
const basename = src.path.split('/').pop() ?? '';
|
|
421
475
|
if (basename === requestedFilename) {
|
|
422
476
|
const absolutePath = normalize(resolve(src.path));
|
|
423
|
-
// Verify the resolved path hasn't escaped (extra safety)
|
|
424
477
|
if (!existsSync(absolutePath)) {
|
|
425
478
|
res.statusCode = 404;
|
|
426
479
|
res.end('Not found');
|
|
@@ -571,10 +624,11 @@ export function timberFonts(ctx: PluginContext): Plugin {
|
|
|
571
624
|
}
|
|
572
625
|
|
|
573
626
|
if (transformedCode !== code) {
|
|
574
|
-
// Inject
|
|
575
|
-
//
|
|
576
|
-
|
|
577
|
-
|
|
627
|
+
// Inject side-effect import that registers font CSS on globalThis.
|
|
628
|
+
// The RSC entry reads globalThis.__timber_font_css to inline a <style> tag.
|
|
629
|
+
if (registry.size > 0) {
|
|
630
|
+
transformedCode = `import '${VIRTUAL_FONT_CSS_REGISTER}';\n` + transformedCode;
|
|
631
|
+
}
|
|
578
632
|
return { code: transformedCode, map: null };
|
|
579
633
|
}
|
|
580
634
|
|
|
@@ -620,15 +674,8 @@ export function timberFonts(ctx: PluginContext): Plugin {
|
|
|
620
674
|
}
|
|
621
675
|
}
|
|
622
676
|
|
|
623
|
-
//
|
|
624
|
-
|
|
625
|
-
if (fontCss) {
|
|
626
|
-
this.emitFile({
|
|
627
|
-
type: 'asset',
|
|
628
|
-
fileName: '_timber/fonts/fonts.css',
|
|
629
|
-
source: fontCss,
|
|
630
|
-
});
|
|
631
|
-
}
|
|
677
|
+
// Font CSS is emitted by Vite's CSS pipeline via virtual:timber-font-css modules.
|
|
678
|
+
// We only need to emit font binary files and update the build manifest here.
|
|
632
679
|
|
|
633
680
|
if (!ctx.buildManifest) return;
|
|
634
681
|
|
package/src/plugins/mdx.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 MDX_EXTENSIONS = ['mdx', 'md'];
|
|
17
17
|
|
package/src/plugins/routing.ts
CHANGED
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
import type { Plugin, ViteDevServer } from 'vite';
|
|
12
12
|
import { writeFile, mkdir } from 'node:fs/promises';
|
|
13
13
|
import { join } from 'node:path';
|
|
14
|
-
import { scanRoutes } from '
|
|
15
|
-
import { generateRouteMap } from '
|
|
16
|
-
import { collectInterceptionRewrites } from '
|
|
14
|
+
import { scanRoutes } from '../routing/scanner.js';
|
|
15
|
+
import { generateRouteMap } from '../routing/codegen.js';
|
|
16
|
+
import { collectInterceptionRewrites } from '../routing/interception.js';
|
|
17
17
|
import {
|
|
18
18
|
lintStatusFileDirectives,
|
|
19
19
|
formatStatusFileLintWarnings,
|
|
20
|
-
} from '
|
|
21
|
-
import type { RouteTree, SegmentNode, RouteFile } from '
|
|
22
|
-
import type { PluginContext } from '
|
|
20
|
+
} from '../routing/status-file-lint.js';
|
|
21
|
+
import type { RouteTree, SegmentNode, RouteFile } from '../routing/types.js';
|
|
22
|
+
import type { PluginContext } from '../index.js';
|
|
23
23
|
|
|
24
24
|
const VIRTUAL_MODULE_ID = 'virtual:timber-route-manifest';
|
|
25
25
|
const RESOLVED_VIRTUAL_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
@@ -28,7 +28,7 @@ const RESOLVED_VIRTUAL_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
|
28
28
|
* File convention names we track for changes that require manifest regeneration.
|
|
29
29
|
*/
|
|
30
30
|
const ROUTE_FILE_PATTERNS =
|
|
31
|
-
/\/(page|layout|middleware|access|route|error|default|denied|
|
|
31
|
+
/\/(page|layout|middleware|access|route|error|default|denied|params|\d{3}|[45]xx|not-found|forbidden|unauthorized|sitemap|robots|manifest|favicon|icon|opengraph-image|twitter-image|apple-icon)\./;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Create the timber-routing Vite plugin.
|
|
@@ -168,20 +168,49 @@ export function timberRouting(ctx: PluginContext): Plugin {
|
|
|
168
168
|
// Watch the app directory
|
|
169
169
|
devServer.watcher.add(ctx.appDir);
|
|
170
170
|
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
/** Snapshot of the last generated manifest, used to detect structural changes. */
|
|
172
|
+
let lastManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree) : '';
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Handle a route-significant file being added or removed.
|
|
176
|
+
* Always triggers a full-reload since the route tree structure changed.
|
|
177
|
+
*/
|
|
178
|
+
const handleStructuralChange = (filePath: string) => {
|
|
173
179
|
if (!filePath.startsWith(ctx.appDir)) return;
|
|
174
180
|
if (!ROUTE_FILE_PATTERNS.test(filePath)) return;
|
|
175
181
|
|
|
176
|
-
// Rescan the route tree
|
|
177
182
|
rescan();
|
|
178
|
-
|
|
179
|
-
// Invalidate the virtual module in all environments
|
|
183
|
+
lastManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree) : '';
|
|
180
184
|
invalidateManifest(devServer);
|
|
181
185
|
};
|
|
182
186
|
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
/**
|
|
188
|
+
* Handle a route file's content changing.
|
|
189
|
+
*
|
|
190
|
+
* Most content edits (JSX changes, fixing typos) don't affect route
|
|
191
|
+
* metadata — Vite's React Fast Refresh handles those via normal HMR.
|
|
192
|
+
* Only rescan and full-reload when route metadata actually changed
|
|
193
|
+
* (e.g., searchParams export added/removed, metadata export changed).
|
|
194
|
+
*/
|
|
195
|
+
const handleContentChange = (filePath: string) => {
|
|
196
|
+
if (!filePath.startsWith(ctx.appDir)) return;
|
|
197
|
+
if (!ROUTE_FILE_PATTERNS.test(filePath)) return;
|
|
198
|
+
|
|
199
|
+
rescan();
|
|
200
|
+
const newManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree) : '';
|
|
201
|
+
if (newManifest !== lastManifest) {
|
|
202
|
+
lastManifest = newManifest;
|
|
203
|
+
invalidateManifest(devServer);
|
|
204
|
+
}
|
|
205
|
+
// Otherwise: content edit didn't change route metadata — let Vite HMR handle it
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
devServer.watcher.on('add', handleStructuralChange);
|
|
209
|
+
devServer.watcher.on('unlink', handleStructuralChange);
|
|
210
|
+
// Watch content changes to page files — searchParams detection depends
|
|
211
|
+
// on file contents (export const searchParams), not just file presence.
|
|
212
|
+
// But only full-reload when route metadata actually changes.
|
|
213
|
+
devServer.watcher.on('change', handleContentChange);
|
|
185
214
|
// Also watch renames (which are add+unlink) — handled by the above
|
|
186
215
|
},
|
|
187
216
|
};
|
|
@@ -301,12 +330,15 @@ function generateManifestModule(tree: RouteTree): string {
|
|
|
301
330
|
`${nextIndent}denied: { load: ${v}, filePath: ${JSON.stringify(node.denied.filePath)} },`
|
|
302
331
|
);
|
|
303
332
|
}
|
|
304
|
-
if (node.
|
|
305
|
-
const v = addImport(node.
|
|
333
|
+
if (node.params) {
|
|
334
|
+
const v = addImport(node.params);
|
|
306
335
|
parts.push(
|
|
307
|
-
`${nextIndent}
|
|
336
|
+
`${nextIndent}params: { load: ${v}, filePath: ${JSON.stringify(node.params.filePath)} },`
|
|
308
337
|
);
|
|
309
338
|
}
|
|
339
|
+
// searchParams is now a named export from page.tsx, not a separate file.
|
|
340
|
+
// The page module's searchParams export is loaded via the page's lazy import.
|
|
341
|
+
// Runtime registration happens in the route loader using the page module.
|
|
310
342
|
|
|
311
343
|
// Status-code files
|
|
312
344
|
if (node.statusFiles && node.statusFiles.size > 0) {
|
|
@@ -391,6 +423,13 @@ function generateManifestModule(tree: RouteTree): string {
|
|
|
391
423
|
proxyLine = ` proxy: { load: ${v}, filePath: ${JSON.stringify(tree.proxy.filePath)} },`;
|
|
392
424
|
}
|
|
393
425
|
|
|
426
|
+
// Global error page (Tier 2)
|
|
427
|
+
let globalErrorLine = '';
|
|
428
|
+
if (tree.globalError) {
|
|
429
|
+
const v = addImport(tree.globalError);
|
|
430
|
+
globalErrorLine = ` globalError: { load: ${v}, filePath: ${JSON.stringify(tree.globalError.filePath)} },`;
|
|
431
|
+
}
|
|
432
|
+
|
|
394
433
|
// Interception rewrites — computed at build time from the route tree.
|
|
395
434
|
// Only interceptedPattern and interceptingPrefix are needed at runtime.
|
|
396
435
|
const rewrites = collectInterceptionRewrites(tree.root);
|
|
@@ -407,6 +446,7 @@ function generateManifestModule(tree: RouteTree): string {
|
|
|
407
446
|
'',
|
|
408
447
|
'const manifest = {',
|
|
409
448
|
proxyLine,
|
|
449
|
+
globalErrorLine,
|
|
410
450
|
rewritesLine,
|
|
411
451
|
` root: ${rootSerialized},`,
|
|
412
452
|
'};',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Plugin } from 'vite';
|
|
2
2
|
import { Parser } from 'acorn';
|
|
3
3
|
import acornJsx from 'acorn-jsx';
|
|
4
|
-
import { detectFileDirective } from '
|
|
4
|
+
import { detectFileDirective } from '../utils/directive-parser.js';
|
|
5
5
|
|
|
6
6
|
const jsxParser = Parser.extend(acornJsx());
|
|
7
7
|
|
|
@@ -137,5 +137,36 @@ export function timberServerBundle(): Plugin[] {
|
|
|
137
137
|
},
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
// Fix Rolldown's `createRequire(import.meta.url)` CJS interop shim for
|
|
141
|
+
// Cloudflare Workers. Rolldown emits this for CJS dependencies (e.g.
|
|
142
|
+
// @opentelemetry/context-async-hooks) that use `require()`. On Workers,
|
|
143
|
+
// `import.meta.url` is `undefined` for non-entry modules, causing:
|
|
144
|
+
// TypeError: The argument 'path' must be a file URL object, a file URL
|
|
145
|
+
// string, or an absolute path string. Received 'undefined'
|
|
146
|
+
//
|
|
147
|
+
// The fix: provide a fallback URL when `import.meta.url` is undefined.
|
|
148
|
+
// The actual URL doesn't matter — `createRequire` only needs it for
|
|
149
|
+
// resolving relative paths, but the only `__require()` calls are for
|
|
150
|
+
// Node built-ins (events, async_hooks) which resolve from any base.
|
|
151
|
+
//
|
|
152
|
+
// The top-level `ssr: { target: 'webworker' }` was supposed to prevent
|
|
153
|
+
// this, but it doesn't propagate to custom environments (rsc) in Vite's
|
|
154
|
+
// Environment API. See LOCAL-405.
|
|
155
|
+
const createRequireFixPlugin: Plugin = {
|
|
156
|
+
name: 'timber-create-require-fix',
|
|
157
|
+
applyToEnvironment(environment) {
|
|
158
|
+
return environment.name === 'rsc' || environment.name === 'ssr';
|
|
159
|
+
},
|
|
160
|
+
renderChunk(code) {
|
|
161
|
+
const pattern = 'createRequire(import.meta.url)';
|
|
162
|
+
if (!code.includes(pattern)) return null;
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
code: code.replace(pattern, 'createRequire(import.meta.url || "file:///app")'),
|
|
166
|
+
map: null,
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
return [bundlePlugin, esmInitFixPlugin, createRequireFixPlugin];
|
|
141
172
|
}
|
package/src/plugins/shims.ts
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* shim implementations. This enables Next.js-compatible libraries
|
|
6
6
|
* (nuqs, next-intl, etc.) to work unmodified.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* This plugin also remaps ALL @timber-js/app/* subpath imports to src/ in
|
|
9
|
+
* server environments (RSC + SSR). This is required because dist/ chunks
|
|
10
|
+
* are pre-built and miss Vite's RSC transforms (e.g. createContext from
|
|
11
|
+
* 'react' doesn't exist in RSC's React build). It also ensures a single
|
|
12
|
+
* module instance for shared mutable state. See SUBPATH_SRC_MAP and TIM-568.
|
|
12
13
|
*
|
|
13
14
|
* Design doc: 18-build-system.md §"Shim Map"
|
|
14
15
|
*/
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
import type { Plugin } from 'vite';
|
|
17
18
|
import { resolve, dirname } from 'node:path';
|
|
18
19
|
import { fileURLToPath } from 'node:url';
|
|
19
|
-
import type { PluginContext } from '
|
|
20
|
+
import type { PluginContext } from '../index.js';
|
|
20
21
|
|
|
21
22
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
22
23
|
// Detect whether we're running from source (src/plugins/) or dist (dist/).
|
|
@@ -38,6 +39,24 @@ const SHIMS_DIR = resolve(PKG_ROOT, 'src', 'shims');
|
|
|
38
39
|
const SERVER_ONLY_VIRTUAL = '\0timber:server-only';
|
|
39
40
|
const CLIENT_ONLY_VIRTUAL = '\0timber:client-only';
|
|
40
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Map from @timber-js/app/<subpath> to relative src/ file paths.
|
|
44
|
+
*
|
|
45
|
+
* Used by the catch-all resolveId rule to remap subpath imports to src/
|
|
46
|
+
* in server environments. When adding a new subpath export to package.json,
|
|
47
|
+
* add it here too. See TIM-568.
|
|
48
|
+
*/
|
|
49
|
+
const SUBPATH_SRC_MAP: Record<string, string> = {
|
|
50
|
+
'cache': 'cache/index.ts',
|
|
51
|
+
'content': 'content/index.ts',
|
|
52
|
+
'cookies': 'cookies/index.ts',
|
|
53
|
+
'params': 'params/index.ts',
|
|
54
|
+
'search-params': 'search-params/index.ts',
|
|
55
|
+
'routing': 'routing/index.ts',
|
|
56
|
+
'adapters/cloudflare': 'adapters/cloudflare.ts',
|
|
57
|
+
'adapters/nitro': 'adapters/nitro.ts',
|
|
58
|
+
};
|
|
59
|
+
|
|
41
60
|
/**
|
|
42
61
|
* Map from next/* import specifiers to shim file paths.
|
|
43
62
|
*
|
|
@@ -88,14 +107,14 @@ export function timberShims(_ctx: PluginContext): Plugin {
|
|
|
88
107
|
* 3. Check next/* shim map
|
|
89
108
|
* 4. Return null (pass through) for everything else
|
|
90
109
|
*
|
|
91
|
-
* @timber-js/app
|
|
92
|
-
*
|
|
93
|
-
*
|
|
110
|
+
* All @timber-js/app/* subpath imports resolve to dist/ via package.json
|
|
111
|
+
* exports in all environments. This ensures a single module instance
|
|
112
|
+
* for each module — the dist/ chunks share code via rollup's code
|
|
113
|
+
* splitting. No src/ remapping is needed (see TIM-568).
|
|
94
114
|
*
|
|
95
|
-
* @timber-js/app/
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* is preserved on the entry for client boundary detection.
|
|
115
|
+
* The only exception is @timber-js/app/server in the client (browser)
|
|
116
|
+
* environment, which returns a virtual stub — server code must never
|
|
117
|
+
* be bundled into the browser.
|
|
99
118
|
*/
|
|
100
119
|
resolveId(id: string) {
|
|
101
120
|
// Poison pill packages — resolve to virtual modules handled by load()
|
|
@@ -117,38 +136,57 @@ export function timberShims(_ctx: PluginContext): Plugin {
|
|
|
117
136
|
return SHIM_MAP[cleanId];
|
|
118
137
|
}
|
|
119
138
|
|
|
120
|
-
// @timber-js/app
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
139
|
+
// ── @timber-js/app/* → src/ resolution in server environments ──
|
|
140
|
+
//
|
|
141
|
+
// All @timber-js/app/* subpath imports are remapped to src/ in server
|
|
142
|
+
// environments (RSC + SSR). This is required for two reasons:
|
|
143
|
+
//
|
|
144
|
+
// 1. RSC correctness: dist/ chunks eagerly import from 'react' (e.g.
|
|
145
|
+
// createContext in segment-context) which doesn't exist in RSC's
|
|
146
|
+
// React build. Vite's RSC plugin only transforms src/ files —
|
|
147
|
+
// dist/ chunks are pre-built and served as-is.
|
|
148
|
+
//
|
|
149
|
+
// 2. Module singleton correctness: framework internals use relative
|
|
150
|
+
// imports that resolve within src/. If user code resolved to dist/
|
|
151
|
+
// while framework code resolved to src/, mutable module-level state
|
|
152
|
+
// (ALS refs, registered callbacks) would be duplicated. By remapping
|
|
153
|
+
// all @timber-js/app/* to src/, everything shares one module graph.
|
|
154
|
+
//
|
|
155
|
+
// Exception: @timber-js/app/client in RSC resolves to dist/ where
|
|
156
|
+
// 'use client' is preserved for client boundary detection.
|
|
157
|
+
//
|
|
158
|
+
// In the client (browser) environment, all imports resolve to dist/
|
|
159
|
+
// via package.json exports (no remapping needed).
|
|
160
|
+
|
|
124
161
|
if (cleanId === '@timber-js/app/server') {
|
|
125
162
|
const envName = (this as unknown as { environment?: { name?: string } }).environment?.name;
|
|
126
163
|
if (envName === 'client') {
|
|
127
164
|
return '\0timber:server-empty';
|
|
128
165
|
}
|
|
166
|
+
// RSC + SSR: remap to src/
|
|
129
167
|
return resolve(PKG_ROOT, 'src', 'server', 'index.ts');
|
|
130
168
|
}
|
|
131
169
|
|
|
132
|
-
// @timber-js/app/client → src/ in the SSR environment so client hooks
|
|
133
|
-
// (useParams, usePathname, etc.) share the same module instance as
|
|
134
|
-
// ssr-entry.ts's internal imports (via #/client/...).
|
|
135
|
-
//
|
|
136
|
-
// Without this remap, @timber-js/app/client resolves to dist/ (via
|
|
137
|
-
// package.json exports), creating a module instance split: ssr-entry.ts
|
|
138
|
-
// registers the ALS-backed SSR data provider on the src/ instance of
|
|
139
|
-
// ssr-data.ts, but client component hooks read getSsrData() from the
|
|
140
|
-
// dist/ instance — which has no provider. Result: hooks like useParams()
|
|
141
|
-
// return empty defaults during SSR.
|
|
142
|
-
//
|
|
143
|
-
// This remap is SSR-only. The RSC environment still resolves to dist/
|
|
144
|
-
// where 'use client' is preserved on the entry (needed for client
|
|
145
|
-
// boundary detection). The client (browser) environment uses dist/
|
|
146
|
-
// for bundling.
|
|
147
170
|
if (cleanId === '@timber-js/app/client') {
|
|
148
171
|
const envName = (this as unknown as { environment?: { name?: string } }).environment?.name;
|
|
172
|
+
// SSR only — RSC needs dist/ for 'use client' boundary detection
|
|
149
173
|
if (envName === 'ssr') {
|
|
150
174
|
return resolve(PKG_ROOT, 'src', 'client', 'index.ts');
|
|
151
175
|
}
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Catch-all: remap any other @timber-js/app/<subpath> to src/
|
|
180
|
+
// in non-client environments (RSC + SSR).
|
|
181
|
+
if (cleanId.startsWith('@timber-js/app/') && cleanId !== '@timber-js/app/package.json') {
|
|
182
|
+
const envName = (this as unknown as { environment?: { name?: string } }).environment?.name;
|
|
183
|
+
if (envName !== 'client') {
|
|
184
|
+
const subpath = cleanId.slice('@timber-js/app/'.length);
|
|
185
|
+
const srcPath = SUBPATH_SRC_MAP[subpath];
|
|
186
|
+
if (srcPath) {
|
|
187
|
+
return resolve(PKG_ROOT, 'src', srcPath);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
152
190
|
}
|
|
153
191
|
|
|
154
192
|
return null;
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { Plugin } from 'vite';
|
|
13
|
-
import type { PluginContext } from '
|
|
14
|
-
import { detectFileDirective } from '
|
|
13
|
+
import type { PluginContext } from '../index.js';
|
|
14
|
+
import { detectFileDirective } from '../utils/directive-parser.js';
|
|
15
15
|
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
// Types
|
|
@@ -163,9 +163,6 @@ export function validateStaticMode(
|
|
|
163
163
|
* - transform: Validates source files for static mode violations
|
|
164
164
|
*/
|
|
165
165
|
export function timberStaticBuild(ctx: PluginContext): Plugin {
|
|
166
|
-
const isStatic = ctx.config.output === 'static';
|
|
167
|
-
const clientJavascriptDisabled = ctx.clientJavascript.disabled;
|
|
168
|
-
|
|
169
166
|
return {
|
|
170
167
|
name: 'timber-static-build',
|
|
171
168
|
|
|
@@ -177,6 +174,11 @@ export function timberStaticBuild(ctx: PluginContext): Plugin {
|
|
|
177
174
|
* - When client JS disabled: 'use client' / 'use server' directives → build error
|
|
178
175
|
*/
|
|
179
176
|
transform(code: string, id: string) {
|
|
177
|
+
// Read ctx.config lazily inside the hook — not at plugin construction
|
|
178
|
+
// time — so file-based config from timber.config.ts is respected.
|
|
179
|
+
// See TIM-451.
|
|
180
|
+
const isStatic = ctx.config.output === 'static';
|
|
181
|
+
|
|
180
182
|
// Only active in static mode
|
|
181
183
|
if (!isStatic) return null;
|
|
182
184
|
|
|
@@ -189,7 +191,9 @@ export function timberStaticBuild(ctx: PluginContext): Plugin {
|
|
|
189
191
|
// Only check JS/TS files
|
|
190
192
|
if (!/\.[jt]sx?$/.test(id)) return null;
|
|
191
193
|
|
|
192
|
-
const errors = validateStaticMode(code, id, {
|
|
194
|
+
const errors = validateStaticMode(code, id, {
|
|
195
|
+
clientJavascriptDisabled: ctx.clientJavascript.disabled,
|
|
196
|
+
});
|
|
193
197
|
|
|
194
198
|
if (errors.length > 0) {
|
|
195
199
|
// Format all errors into a single build error message
|