@timber-js/app 0.2.0-alpha.6 → 0.2.0-alpha.61
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-CT98cU9c.js +121 -0
- package/dist/_chunks/define-CT98cU9c.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-BWr_52kY.js +93 -0
- package/dist/_chunks/define-cookie-BWr_52kY.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-rju2rbga.js} +97 -69
- package/dist/_chunks/request-context-rju2rbga.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-BSSym1MJ.js +64 -0
- package/dist/_chunks/stale-reload-BSSym1MJ.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 +665 -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 +1977 -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 +151 -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 +90 -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 +73 -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 +327 -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 +284 -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 +29 -14
- 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 +148 -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 +286 -81
- package/src/server/rsc-entry/helpers.ts +134 -5
- package/src/server/rsc-entry/index.ts +177 -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 +152 -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 +213 -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
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* defineParams — factory for typed route param coercion.
|
|
3
|
+
*
|
|
4
|
+
* Creates a ParamsDefinition that coerces raw string params from the
|
|
5
|
+
* URL into typed values. Used by exporting from layout.tsx (segment-level)
|
|
6
|
+
* or page.tsx (fallback).
|
|
7
|
+
*
|
|
8
|
+
* Reuses the shared Codec<T> protocol with Standard Schema auto-detection,
|
|
9
|
+
* same pattern as defineSearchParams. Runtime constraints are stricter:
|
|
10
|
+
* - serialize must return string (not null — path segments can't be omitted)
|
|
11
|
+
* - parse throwing → 404 (invalid param value)
|
|
12
|
+
*
|
|
13
|
+
* Design doc: design/07a-route-params-triage.md
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { Codec } from '../codec.js';
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Server-only ALS reference for .load()
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
// Same pattern as search-params: eagerly registered at server startup
|
|
23
|
+
// to avoid dynamic imports that lose ALS context. See TIM-523.
|
|
24
|
+
let _rawSegmentParams: (() => Promise<Record<string, string | string[]>>) | undefined;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Register the rawSegmentParams function. Called once at module load time
|
|
28
|
+
* from request-context.ts to avoid dynamic import at call time.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export function _setRawSegmentParamsFn(fn: () => Promise<Record<string, string | string[]>>): void {
|
|
32
|
+
_rawSegmentParams = fn;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getRawSegmentParams(): Promise<Record<string, string | string[]>> {
|
|
36
|
+
if (!_rawSegmentParams) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
'[timber] segmentParams.load() is only available on the server. ' +
|
|
39
|
+
'Use useSegmentParams() on the client.'
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return _rawSegmentParams();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Types
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
/** Infer the output type from a Codec or StandardSchemaV1. */
|
|
50
|
+
export type InferParamField<V> =
|
|
51
|
+
V extends Codec<infer T> ? T : V extends StandardSchemaV1<infer T> ? T : never;
|
|
52
|
+
|
|
53
|
+
/** Acceptable field value for defineParams: a Codec or a Standard Schema. */
|
|
54
|
+
export type ParamField<T = unknown> = Codec<T> | StandardSchemaV1<T>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A typed route params definition.
|
|
58
|
+
*
|
|
59
|
+
* Returned by defineParams(). Provides parse (string → typed) and
|
|
60
|
+
* serialize (typed → string) for each declared param.
|
|
61
|
+
*/
|
|
62
|
+
export interface ParamsDefinition<T extends Record<string, unknown>> {
|
|
63
|
+
/** Parse raw string params into typed values. Throws on invalid values. */
|
|
64
|
+
parse(raw: Record<string, string | string[]>): T;
|
|
65
|
+
|
|
66
|
+
/** Serialize typed values back to strings for URL construction. */
|
|
67
|
+
serialize(values: T): Record<string, string>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Load typed segment params from the current request context (ALS).
|
|
71
|
+
*
|
|
72
|
+
* Server-only. Reads rawSegmentParams() from ALS and coerces through
|
|
73
|
+
* this definition's codecs, returning fully typed params.
|
|
74
|
+
*
|
|
75
|
+
* ```ts
|
|
76
|
+
* // app/products/[id]/params.ts
|
|
77
|
+
* export const segmentParams = defineSegmentParams({ id: z.coerce.number() })
|
|
78
|
+
*
|
|
79
|
+
* // app/products/[id]/page.tsx
|
|
80
|
+
* import { segmentParams } from './params'
|
|
81
|
+
* export default async function Page() {
|
|
82
|
+
* const { id } = await segmentParams.load() // id: number
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
load(): Promise<T>;
|
|
87
|
+
|
|
88
|
+
/** Read-only codec map. */
|
|
89
|
+
codecs: { [K in keyof T]: Codec<T[K]> };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// Standard Schema interface (subset — same as in search-params/define.ts)
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
interface StandardSchemaV1<Output = unknown> {
|
|
97
|
+
'~standard': {
|
|
98
|
+
validate(
|
|
99
|
+
value: unknown
|
|
100
|
+
):
|
|
101
|
+
| { value: Output; issues?: undefined }
|
|
102
|
+
| { value?: undefined; issues: ReadonlyArray<{ message: string }> }
|
|
103
|
+
| Promise<
|
|
104
|
+
| { value: Output; issues?: undefined }
|
|
105
|
+
| { value?: undefined; issues: ReadonlyArray<{ message: string }> }
|
|
106
|
+
>;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
// Internal helpers
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
|
|
114
|
+
function isStandardSchema(value: unknown): value is StandardSchemaV1 {
|
|
115
|
+
return (
|
|
116
|
+
typeof value === 'object' &&
|
|
117
|
+
value !== null &&
|
|
118
|
+
'~standard' in value &&
|
|
119
|
+
typeof (value as StandardSchemaV1)['~standard']?.validate === 'function'
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function isCodec(value: unknown): value is Codec<unknown> {
|
|
124
|
+
return (
|
|
125
|
+
typeof value === 'object' &&
|
|
126
|
+
value !== null &&
|
|
127
|
+
typeof (value as Codec<unknown>).parse === 'function' &&
|
|
128
|
+
typeof (value as Codec<unknown>).serialize === 'function'
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Validate sync for Standard Schema (same helper as search-params/codecs.ts).
|
|
134
|
+
*/
|
|
135
|
+
function validateSync<Output>(
|
|
136
|
+
schema: StandardSchemaV1<Output>,
|
|
137
|
+
value: unknown
|
|
138
|
+
):
|
|
139
|
+
| { value: Output; issues?: undefined }
|
|
140
|
+
| { value?: undefined; issues: ReadonlyArray<{ message: string }> } {
|
|
141
|
+
const result = schema['~standard'].validate(value);
|
|
142
|
+
if (result instanceof Promise) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
'[timber] defineParams: schema returned a Promise — only sync schemas are supported.'
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Wrap a Standard Schema into a Codec for route params.
|
|
152
|
+
*
|
|
153
|
+
* Unlike fromSchema for search params:
|
|
154
|
+
* - Parse throws on failure (no fallback to default)
|
|
155
|
+
* - Serialize returns string (not null)
|
|
156
|
+
*/
|
|
157
|
+
function fromParamSchema<T>(fieldName: string, schema: StandardSchemaV1<T>): Codec<T> {
|
|
158
|
+
return {
|
|
159
|
+
parse(value: string | string[] | undefined): T {
|
|
160
|
+
// Route params are always strings (single segment) or string[] (catch-all)
|
|
161
|
+
const input = Array.isArray(value) ? value : value;
|
|
162
|
+
|
|
163
|
+
const result = validateSync(schema, input);
|
|
164
|
+
if (!result.issues) {
|
|
165
|
+
return result.value;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// For route params, parse failure means the param is invalid → throw
|
|
169
|
+
const messages = result.issues.map((i) => i.message).join(', ');
|
|
170
|
+
throw new Error(`[timber] Param '${fieldName}' coercion failed: ${messages}`);
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
serialize(value: T): string | null {
|
|
174
|
+
if (value === null || value === undefined) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
// Catch-all segments produce arrays — join with '/' for path reconstruction
|
|
178
|
+
if (Array.isArray(value)) {
|
|
179
|
+
return value.join('/');
|
|
180
|
+
}
|
|
181
|
+
return String(value);
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Resolve a field value to a Codec. Auto-detects Standard Schema objects.
|
|
188
|
+
*/
|
|
189
|
+
function resolveField(fieldName: string, value: ParamField): Codec<unknown> {
|
|
190
|
+
if (isCodec(value)) {
|
|
191
|
+
return value;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (isStandardSchema(value)) {
|
|
195
|
+
return fromParamSchema(fieldName, value);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
throw new Error(
|
|
199
|
+
`[timber] defineParams: field '${fieldName}' is not a valid codec or Standard Schema. ` +
|
|
200
|
+
`Expected an object with { parse, serialize } methods, or a Standard Schema object ` +
|
|
201
|
+
`(Zod, Valibot, ArkType).`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Validate that no codec's serialize returns null.
|
|
207
|
+
* Route params are structural — they must produce a valid path segment.
|
|
208
|
+
*/
|
|
209
|
+
function validateSerialize(codecMap: Record<string, Codec<unknown>>): void {
|
|
210
|
+
for (const [key, codec] of Object.entries(codecMap)) {
|
|
211
|
+
// Test serialize with a sample parsed value to check for null
|
|
212
|
+
// We can't exhaustively test, but we can check that serialize(parse("test"))
|
|
213
|
+
// doesn't return null for a basic input.
|
|
214
|
+
try {
|
|
215
|
+
const testValue = codec.parse('test');
|
|
216
|
+
const serialized = codec.serialize(testValue);
|
|
217
|
+
if (serialized === null) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`[timber] defineParams: field '${key}' codec.serialize() returned null.\n` +
|
|
220
|
+
` Route params are path segments — they cannot be omitted.\n` +
|
|
221
|
+
` Ensure serialize() always returns a string.`
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
} catch (e) {
|
|
225
|
+
// parse('test') may throw for strict codecs (e.g., number-only).
|
|
226
|
+
// That's fine — it means the codec validates. We only care about
|
|
227
|
+
// serialize returning null, which we can't test without a valid value.
|
|
228
|
+
if (e instanceof Error && e.message.includes('returned null')) {
|
|
229
|
+
throw e;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
// Factory
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Create a ParamsDefinition from a map of codecs and/or Standard Schema objects.
|
|
241
|
+
*
|
|
242
|
+
* ```ts
|
|
243
|
+
* // app/products/[id]/layout.tsx
|
|
244
|
+
* import { defineParams } from '@timber-js/app/params'
|
|
245
|
+
* import { z } from 'zod/v4'
|
|
246
|
+
*
|
|
247
|
+
* export const params = defineParams({
|
|
248
|
+
* id: z.coerce.number().int().positive(),
|
|
249
|
+
* })
|
|
250
|
+
*
|
|
251
|
+
* export default function Layout({ children }) { return children }
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
export function defineSegmentParams<C extends Record<string, ParamField>>(
|
|
255
|
+
codecs: C
|
|
256
|
+
): ParamsDefinition<{ [K in keyof C]: InferParamField<C[K]> }> {
|
|
257
|
+
type T = { [K in keyof C]: InferParamField<C[K]> };
|
|
258
|
+
|
|
259
|
+
const resolvedCodecs: Record<string, Codec<unknown>> = {};
|
|
260
|
+
|
|
261
|
+
for (const [key, value] of Object.entries(codecs)) {
|
|
262
|
+
resolvedCodecs[key] = resolveField(key, value as ParamField);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Validate that serialize doesn't return null
|
|
266
|
+
validateSerialize(resolvedCodecs);
|
|
267
|
+
|
|
268
|
+
// ---- parse ----
|
|
269
|
+
function parse(raw: Record<string, string | string[]>): T {
|
|
270
|
+
const result: Record<string, unknown> = {};
|
|
271
|
+
|
|
272
|
+
for (const [key, codec] of Object.entries(resolvedCodecs)) {
|
|
273
|
+
const rawValue = raw[key];
|
|
274
|
+
// Route params are always present (the route matched)
|
|
275
|
+
result[key] = codec.parse(rawValue);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return result as T;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ---- serialize ----
|
|
282
|
+
function serialize(values: T): Record<string, string> {
|
|
283
|
+
const result: Record<string, string> = {};
|
|
284
|
+
|
|
285
|
+
for (const [key, codec] of Object.entries(resolvedCodecs)) {
|
|
286
|
+
const serialized = codec.serialize(values[key as keyof T] as unknown);
|
|
287
|
+
if (serialized === null) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
`[timber] params.serialize: field '${key}' serialized to null. ` +
|
|
290
|
+
`Route params must produce a valid path segment.`
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
result[key] = serialized;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return result;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// ---- load ----
|
|
300
|
+
// ALS-backed: reads segment params from the current request context.
|
|
301
|
+
// Server-only — throws on client.
|
|
302
|
+
//
|
|
303
|
+
// The pipeline already coerces params via coerceSegmentParams() which
|
|
304
|
+
// calls parse() and stores typed values in ALS via setSegmentParams().
|
|
305
|
+
// We return those directly instead of re-parsing, because codecs may
|
|
306
|
+
// not be idempotent (e.g., a codec that only accepts raw strings would
|
|
307
|
+
// throw if given an already-parsed value). See TIM-574.
|
|
308
|
+
async function load(): Promise<T> {
|
|
309
|
+
if (typeof window !== 'undefined') {
|
|
310
|
+
throw new Error(
|
|
311
|
+
'[timber] segmentParams.load() is server-only. ' + 'Use useSegmentParams() on the client.'
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
const params = await getRawSegmentParams();
|
|
315
|
+
// params are already coerced by the pipeline — return as-is.
|
|
316
|
+
return params as unknown as T;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const definition: ParamsDefinition<T> = {
|
|
320
|
+
parse,
|
|
321
|
+
serialize,
|
|
322
|
+
load,
|
|
323
|
+
codecs: resolvedCodecs as { [K in keyof T]: Codec<T[K]> },
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
return definition;
|
|
327
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @timber-js/app/params — Typed route param coercion and search param definitions
|
|
2
|
+
//
|
|
3
|
+
// This is the primary import path for both segmentParams and searchParams.
|
|
4
|
+
// params.ts convention files import from here.
|
|
5
|
+
//
|
|
6
|
+
// See design/07-routing.md §"params.ts Convention File"
|
|
7
|
+
|
|
8
|
+
// --- Segment params (route path param coercion) ---
|
|
9
|
+
export type { ParamsDefinition, InferParamField, ParamField } from './define.js';
|
|
10
|
+
export { defineSegmentParams } from './define.js';
|
|
11
|
+
|
|
12
|
+
// --- Search params (re-exported from search-params for convenience) ---
|
|
13
|
+
// This lets params.ts import both from a single path:
|
|
14
|
+
// import { defineSegmentParams, defineSearchParams } from '@timber-js/app/params'
|
|
15
|
+
export { defineSearchParams } from '../search-params/define.js';
|
|
16
|
+
|
|
17
|
+
// --- Codec utilities (re-exported for convenience) ---
|
|
18
|
+
export { fromSchema, fromArraySchema } from '../search-params/codecs.js';
|
|
19
|
+
export { withDefault, withUrlKey } from '../search-params/wrappers.js';
|
|
20
|
+
export type { Codec } from '../codec.js';
|
|
21
|
+
export type {
|
|
22
|
+
SearchParamCodec,
|
|
23
|
+
SearchParamsDefinition,
|
|
24
|
+
SetParams,
|
|
25
|
+
SetParamsOptions,
|
|
26
|
+
QueryStatesOptions,
|
|
27
|
+
CodecMap,
|
|
28
|
+
} from '../search-params/define.js';
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
import type { Plugin } from 'vite';
|
|
17
17
|
import { join } from 'node:path';
|
|
18
18
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
19
|
-
import type { PluginContext } from '
|
|
20
|
-
import type { TimberPlatformAdapter, TimberConfig } from '
|
|
19
|
+
import type { PluginContext } from '../index.js';
|
|
20
|
+
import type { TimberPlatformAdapter, TimberConfig } from '../adapters/types.js';
|
|
21
21
|
|
|
22
22
|
export function timberAdapterBuild(ctx: PluginContext): Plugin {
|
|
23
23
|
return {
|
|
@@ -50,6 +50,12 @@ export function timberAdapterBuild(ctx: PluginContext): Plugin {
|
|
|
50
50
|
: ctx.buildManifest;
|
|
51
51
|
const json = JSON.stringify(manifest);
|
|
52
52
|
manifestInit = `globalThis.__TIMBER_BUILD_MANIFEST__ = ${json};\n`;
|
|
53
|
+
|
|
54
|
+
// Embed the deployment ID for version skew detection (TIM-446).
|
|
55
|
+
// The server reads this at startup via setDeploymentId().
|
|
56
|
+
if (ctx.deploymentId) {
|
|
57
|
+
manifestInit += `globalThis.__TIMBER_DEPLOYMENT_ID__ = ${JSON.stringify(ctx.deploymentId)};\n`;
|
|
58
|
+
}
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
// Strip JS from the RSC plugin's assets manifest when client JS
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
* Design docs: 18-build-system.md §"Build Manifest", 02-rendering-pipeline.md §"Early Hints"
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import { randomUUID } from 'node:crypto';
|
|
19
20
|
import type { Plugin, ResolvedConfig } from 'vite';
|
|
20
|
-
import type { PluginContext } from '
|
|
21
|
-
import type { BuildManifest } from '
|
|
21
|
+
import type { PluginContext } from '../index.js';
|
|
22
|
+
import type { BuildManifest } from '../server/build-manifest.js';
|
|
22
23
|
|
|
23
24
|
// Rollup types used by generateBundle hook — imported from vite which re-exports them.
|
|
24
25
|
// We define minimal interfaces here to avoid a direct 'rollup' dependency.
|
|
@@ -242,6 +243,16 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
|
|
|
242
243
|
configResolved(config: ResolvedConfig) {
|
|
243
244
|
resolvedBase = config.base;
|
|
244
245
|
isDev = config.command === 'serve';
|
|
246
|
+
|
|
247
|
+
// Generate a per-build deployment ID early so virtual:timber-config
|
|
248
|
+
// can serialize it during the load hook (which runs before generateBundle).
|
|
249
|
+
// A random UUID is used instead of a content hash — determinism provides
|
|
250
|
+
// no real benefit here since you almost never redeploy identical code,
|
|
251
|
+
// and a random ID avoids the timing problem where the content hash was
|
|
252
|
+
// only available after generateBundle (TIM-452).
|
|
253
|
+
if (!isDev && !ctx.deploymentId) {
|
|
254
|
+
ctx.deploymentId = randomUUID().replace(/-/g, '').slice(0, 16);
|
|
255
|
+
}
|
|
245
256
|
},
|
|
246
257
|
|
|
247
258
|
resolveId(id: string) {
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
|
|
16
16
|
import { gzipSync } from 'node:zlib';
|
|
17
17
|
import type { Plugin, Logger } from 'vite';
|
|
18
|
-
import type { PluginContext } from '
|
|
19
|
-
import type { SegmentNode, RouteTree } from '
|
|
20
|
-
import { formatSize } from '
|
|
18
|
+
import type { PluginContext } from '../index.js';
|
|
19
|
+
import type { SegmentNode, RouteTree } from '../routing/types.js';
|
|
20
|
+
import { formatSize } from '../utils/format.js';
|
|
21
21
|
|
|
22
22
|
// ─── Public types ─────────────────────────────────────────────────────────
|
|
23
23
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Plugin } from 'vite';
|
|
2
|
-
import { findFunctionsWithDirective, containsDirective } from '
|
|
2
|
+
import { findFunctionsWithDirective, containsDirective } from '../utils/directive-parser.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Parse a cacheLife duration string to seconds.
|
|
@@ -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',
|