@timber-js/app 0.2.0-alpha.184 → 0.2.0-alpha.186
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/dist/_chunks/{actions-O_LsyCE4.js → actions-C-Rw9vPc.js} +3 -3
- package/dist/_chunks/{actions-O_LsyCE4.js.map → actions-C-Rw9vPc.js.map} +1 -1
- package/dist/_chunks/als-slots-mFweg276.js +27 -0
- package/dist/_chunks/als-slots-mFweg276.js.map +1 -0
- package/dist/_chunks/base-path-DaQrzbez.js +80 -0
- package/dist/_chunks/base-path-DaQrzbez.js.map +1 -0
- package/dist/_chunks/build-manifest-DWppEdLB.js +86 -0
- package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
- package/dist/_chunks/build-output-helper-C3DrfzZR.js +369 -0
- package/dist/_chunks/build-output-helper-C3DrfzZR.js.map +1 -0
- package/dist/_chunks/{cache-api-B-lhk9p4.js → cache-api-Cd0VZ_Pd.js} +3 -3
- package/dist/_chunks/{cache-api-B-lhk9p4.js.map → cache-api-Cd0VZ_Pd.js.map} +1 -1
- package/dist/_chunks/cli-schema-sync-CKgHC2MB.js +1857 -0
- package/dist/_chunks/cli-schema-sync-CKgHC2MB.js.map +1 -0
- package/dist/_chunks/{cloudflare-CnT5Lr7U.js → cloudflare-Cs0uZXea.js} +89 -12
- package/dist/_chunks/{cloudflare-CnT5Lr7U.js.map → cloudflare-Cs0uZXea.js.map} +1 -1
- package/dist/_chunks/error-boundary-DpYRI_I1.js +330 -0
- package/dist/_chunks/error-boundary-DpYRI_I1.js.map +1 -0
- package/dist/_chunks/{fast-hash-D6hIVt1Y.js → fast-hash-C-tVYrLb.js} +6 -1
- package/dist/_chunks/fast-hash-C-tVYrLb.js.map +1 -0
- package/dist/_chunks/fs-identity-D7vb6GdI.js +208 -0
- package/dist/_chunks/fs-identity-D7vb6GdI.js.map +1 -0
- package/dist/_chunks/{logger-AWfuX-KJ.js → logger-N7e5auP0.js} +9 -13
- package/dist/_chunks/logger-N7e5auP0.js.map +1 -0
- package/dist/_chunks/navigation-root-B29qg0_T.js +274 -0
- package/dist/_chunks/navigation-root-B29qg0_T.js.map +1 -0
- package/dist/_chunks/param-value-C8TNYchQ.js +66 -0
- package/dist/_chunks/param-value-C8TNYchQ.js.map +1 -0
- package/dist/_chunks/{plugin-context---kTF5v8.js → plugin-context-DEGLSJs3.js} +2 -1
- package/dist/_chunks/plugin-context-DEGLSJs3.js.map +1 -0
- package/dist/_chunks/{router-ref-CtmF-aPv.js → router-ref-DuYuV_0Q.js} +2 -2
- package/dist/_chunks/router-ref-DuYuV_0Q.js.map +1 -0
- package/dist/_chunks/rsc-cache-key-DD0fl_-s.js +243 -0
- package/dist/_chunks/rsc-cache-key-DD0fl_-s.js.map +1 -0
- package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js +40 -0
- package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js.map +1 -0
- package/dist/_chunks/rsc-payload-path-B_LBodc2.js +48 -0
- package/dist/_chunks/rsc-payload-path-B_LBodc2.js.map +1 -0
- package/dist/_chunks/{segment-classify-Byy425ng.js → segment-classify-C539Pa2O.js} +23 -2
- package/dist/_chunks/segment-classify-C539Pa2O.js.map +1 -0
- package/dist/_chunks/{canonicalize-DQHyFClh.js → segment-keys-BawYuNFO.js} +61 -2
- package/dist/_chunks/segment-keys-BawYuNFO.js.map +1 -0
- package/dist/_chunks/slot-params-BCTmZkQB.js +76 -0
- package/dist/_chunks/slot-params-BCTmZkQB.js.map +1 -0
- package/dist/_chunks/{ssr-data-BOWsq18U.js → ssr-data-14MXm7Pj.js} +17 -2
- package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -0
- package/dist/_chunks/use-segment-params-ClyUNq4d.js +128 -0
- package/dist/_chunks/use-segment-params-ClyUNq4d.js.map +1 -0
- package/dist/_chunks/{walkers-BtTlKviE.js → walkers-BhhwI9TD.js} +21 -87
- package/dist/_chunks/walkers-BhhwI9TD.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +37 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -1
- package/dist/adapters/cloudflare-dev.js +1 -1
- package/dist/adapters/cloudflare-kv-cache.js +1 -1
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +1 -1
- package/dist/adapters/fs-identity.d.ts +64 -0
- package/dist/adapters/fs-identity.d.ts.map +1 -0
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +2 -3
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +57 -1
- package/dist/adapters/shared.d.ts.map +1 -1
- package/dist/adapters/types.d.ts +13 -1
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/cache/fast-hash.d.ts +5 -0
- package/dist/cache/fast-hash.d.ts.map +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/cli.js +2 -2
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
- package/dist/client/browser-entry/hydrate.d.ts +20 -9
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
- package/dist/client/browser-entry/post-hydration.d.ts +4 -1
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
- package/dist/client/browser-entry/router-init.d.ts +3 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -1
- package/dist/client/browser-entry/rsc-stream.d.ts +8 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -1
- package/dist/client/error-boundary.d.ts +1 -0
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -162
- package/dist/client/history.d.ts +13 -6
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.js +18 -11
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +4 -3
- package/dist/client/internal.d.ts.map +1 -1
- package/dist/client/internal.js +872 -305
- package/dist/client/internal.js.map +1 -1
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-api.d.ts +2 -2
- package/dist/client/navigation-commit.d.ts +71 -0
- package/dist/client/navigation-commit.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +37 -20
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/navigation-root.d.ts +63 -23
- package/dist/client/navigation-root.d.ts.map +1 -1
- package/dist/client/params-context.d.ts +81 -0
- package/dist/client/params-context.d.ts.map +1 -0
- package/dist/client/router-effects.d.ts +129 -0
- package/dist/client/router-effects.d.ts.map +1 -0
- package/dist/client/router-lifecycle.d.ts +55 -0
- package/dist/client/router-lifecycle.d.ts.map +1 -0
- package/dist/client/router-pipeline.d.ts +84 -0
- package/dist/client/router-pipeline.d.ts.map +1 -0
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/router-ref.d.ts.map +1 -1
- package/dist/client/router-skew.d.ts +21 -0
- package/dist/client/router-skew.d.ts.map +1 -0
- package/dist/client/router-types.d.ts +207 -0
- package/dist/client/router-types.d.ts.map +1 -0
- package/dist/client/router.d.ts +1 -182
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +39 -16
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +79 -34
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/ssr-data.d.ts +6 -0
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-client.d.ts +69 -0
- package/dist/client/stale-client.d.ts.map +1 -0
- package/dist/client/state.d.ts +10 -1
- package/dist/client/state.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +2 -1
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/unload-guard.d.ts +5 -0
- package/dist/client/unload-guard.d.ts.map +1 -1
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/client/use-segment-params.d.ts +18 -8
- package/dist/client/use-segment-params.d.ts.map +1 -1
- package/dist/cookies/index.js +3 -3
- package/dist/cookies/index.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +915 -320
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +33 -1
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +1 -1
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/request-dep/analysis.d.ts +106 -0
- package/dist/plugins/request-dep/analysis.d.ts.map +1 -0
- package/dist/plugins/request-dep/index.d.ts +75 -0
- package/dist/plugins/request-dep/index.d.ts.map +1 -0
- package/dist/plugins/request-dep/origin.d.ts +61 -0
- package/dist/plugins/request-dep/origin.d.ts.map +1 -0
- package/dist/plugins/routing.d.ts +9 -0
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +149 -8
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-types.d.ts +18 -0
- package/dist/routing/codegen-types.d.ts.map +1 -1
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/collision-probe.d.ts +104 -0
- package/dist/routing/collision-probe.d.ts.map +1 -0
- package/dist/routing/collision-spaces.d.ts +26 -0
- package/dist/routing/collision-spaces.d.ts.map +1 -0
- package/dist/routing/index.js +3 -3
- package/dist/routing/interception.d.ts +235 -6
- package/dist/routing/interception.d.ts.map +1 -1
- package/dist/routing/manifest-codegen.d.ts.map +1 -1
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/segment-classify.d.ts +33 -0
- package/dist/routing/segment-classify.d.ts.map +1 -1
- package/dist/routing/segment-keys.d.ts +95 -0
- package/dist/routing/segment-keys.d.ts.map +1 -0
- package/dist/routing/slot-placement.d.ts +48 -0
- package/dist/routing/slot-placement.d.ts.map +1 -0
- package/dist/routing/types.d.ts +1 -3
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/walkers.d.ts +6 -0
- package/dist/routing/walkers.d.ts.map +1 -1
- package/dist/search-params/define.d.ts +0 -6
- package/dist/search-params/define.d.ts.map +1 -1
- package/dist/search-params/index.js +176 -2
- package/dist/search-params/index.js.map +1 -1
- package/dist/segment-params/define.d.ts +0 -6
- package/dist/segment-params/define.d.ts.map +1 -1
- package/dist/segment-params/index.js +69 -1
- package/dist/segment-params/index.js.map +1 -0
- package/dist/server/actions.d.ts +6 -3
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +2 -1
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +13 -1
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/chain-url-parts.d.ts +82 -0
- package/dist/server/chain-url-parts.d.ts.map +1 -0
- package/dist/server/children-interception.d.ts +49 -0
- package/dist/server/children-interception.d.ts.map +1 -0
- package/dist/server/default-status-page.d.ts +45 -0
- package/dist/server/default-status-page.d.ts.map +1 -0
- package/dist/server/deny-boundary.d.ts +4 -7
- package/dist/server/deny-boundary.d.ts.map +1 -1
- package/dist/server/deny-renderer.d.ts +14 -3
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/head-response.d.ts +35 -0
- package/dist/server/head-response.d.ts.map +1 -0
- package/dist/server/index.js +2 -2
- package/dist/server/internal.js +528 -373
- package/dist/server/internal.js.map +1 -1
- package/dist/server/param-coercion.d.ts +10 -1
- package/dist/server/param-coercion.d.ts.map +1 -1
- package/dist/server/pipeline-helpers.d.ts +0 -18
- package/dist/server/pipeline-helpers.d.ts.map +1 -1
- package/dist/server/pipeline-interception.d.ts +59 -9
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts.map +1 -1
- package/dist/server/pipeline-phases.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +11 -0
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/prebuilt-builder.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +0 -12
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/publish-params.d.ts +33 -0
- package/dist/server/publish-params.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +48 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +32 -2
- 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 +13 -0
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-cache-key-guard.d.ts +78 -0
- package/dist/server/rsc-cache-key-guard.d.ts.map +1 -0
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +14 -2
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +2 -10
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -2
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +3 -2
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +2 -0
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/sitemap-generator.d.ts.map +1 -1
- package/dist/server/skippable-prefix.d.ts +23 -0
- package/dist/server/skippable-prefix.d.ts.map +1 -0
- package/dist/server/slot-interception.d.ts +80 -0
- package/dist/server/slot-interception.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +70 -8
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +6 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +24 -13
- package/dist/server/ssr-wrappers.d.ts.map +1 -1
- package/dist/server/state-tree-diff.d.ts +6 -27
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/static-generator.d.ts +6 -0
- package/dist/server/static-generator.d.ts.map +1 -1
- package/dist/server/static-not-found.d.ts +52 -0
- package/dist/server/static-not-found.d.ts.map +1 -0
- package/dist/server/status-code-resolver.d.ts +3 -10
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/shared/als-slots.d.ts +41 -0
- package/dist/shared/als-slots.d.ts.map +1 -0
- package/dist/shared/base-path.d.ts +56 -0
- package/dist/shared/base-path.d.ts.map +1 -0
- package/dist/shared/param-value.d.ts +80 -0
- package/dist/shared/param-value.d.ts.map +1 -0
- package/dist/shared/payload-root.d.ts +108 -0
- package/dist/shared/payload-root.d.ts.map +1 -0
- package/dist/shared/rsc-cache-key.d.ts +163 -0
- package/dist/shared/rsc-cache-key.d.ts.map +1 -0
- package/dist/shared/rsc-error-envelope.d.ts +25 -0
- package/dist/shared/rsc-error-envelope.d.ts.map +1 -0
- package/dist/shared/rsc-manifest.d.ts +28 -0
- package/dist/shared/rsc-manifest.d.ts.map +1 -0
- package/dist/shared/rsc-payload-path.d.ts +42 -0
- package/dist/shared/rsc-payload-path.d.ts.map +1 -0
- package/dist/shared/segment-info.d.ts +59 -0
- package/dist/shared/segment-info.d.ts.map +1 -0
- package/dist/shared/slot-params.d.ts +51 -0
- package/dist/shared/slot-params.d.ts.map +1 -0
- package/dist/shared/static-platform-files.d.ts +71 -0
- package/dist/shared/static-platform-files.d.ts.map +1 -0
- package/dist/shims/navigation-client.d.ts +8 -19
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +0 -1
- package/dist/shims/navigation.d.ts.map +1 -1
- package/docs/api/31-api-client.mdx +4 -2
- package/docs/learn/02-pages-and-layouts.mdx +1 -1
- package/docs/learn/11-error-handling.mdx +4 -3
- package/docs/learn/12-client-navigation.mdx +2 -2
- package/docs/learn/14-deploying.mdx +23 -0
- package/docs/more/01-advanced-routing.mdx +172 -2
- package/docs/more/04-metadata-and-fonts.mdx +1 -1
- package/package.json +2 -2
- package/src/adapters/build-output-helper.ts +116 -3
- package/src/adapters/cloudflare.ts +86 -11
- package/src/adapters/fs-identity.ts +156 -0
- package/src/adapters/nitro.ts +6 -6
- package/src/adapters/shared.ts +196 -21
- package/src/adapters/types.ts +13 -1
- package/src/cache/fast-hash.ts +5 -0
- package/src/client/browser-entry/action-dispatch.ts +9 -4
- package/src/client/browser-entry/hydrate.ts +40 -29
- package/src/client/browser-entry/index.ts +15 -1
- package/src/client/browser-entry/post-hydration.ts +10 -9
- package/src/client/browser-entry/router-init.ts +104 -48
- package/src/client/browser-entry/rsc-stream.ts +11 -2
- package/src/client/error-boundary.tsx +20 -15
- package/src/client/history.ts +13 -6
- package/src/client/internal.ts +4 -3
- package/src/client/link.tsx +55 -8
- package/src/client/navigation-api.ts +3 -3
- package/src/client/navigation-commit.ts +174 -0
- package/src/client/navigation-context.ts +40 -67
- package/src/client/navigation-root.tsx +326 -101
- package/src/client/params-context.ts +192 -0
- package/src/client/router-effects.ts +231 -0
- package/src/client/router-lifecycle.ts +288 -0
- package/src/client/router-pipeline.ts +389 -0
- package/src/client/router-ref.ts +1 -1
- package/src/client/router-skew.ts +30 -0
- package/src/client/router-types.ts +230 -0
- package/src/client/router.ts +242 -690
- package/src/client/rsc-fetch.ts +180 -122
- package/src/client/segment-cache.ts +121 -44
- package/src/client/ssr-data.ts +6 -0
- package/src/client/stale-client.ts +191 -0
- package/src/client/state.ts +14 -1
- package/src/client/top-loader.tsx +2 -1
- package/src/client/unload-guard.ts +34 -2
- package/src/client/use-cookie.ts +9 -2
- package/src/client/use-router.ts +1 -1
- package/src/client/use-segment-params.ts +41 -18
- package/src/index.ts +5 -1
- package/src/plugin-context.ts +34 -1
- package/src/plugins/adapter-build.ts +4 -0
- package/src/plugins/build-manifest.ts +34 -13
- package/src/plugins/entries.ts +4 -0
- package/src/plugins/fonts.ts +11 -8
- package/src/plugins/request-dep/analysis.ts +447 -0
- package/src/plugins/request-dep/index.ts +376 -0
- package/src/plugins/request-dep/origin.ts +310 -0
- package/src/plugins/routing.ts +60 -3
- package/src/plugins/static-build.ts +333 -63
- package/src/routing/codegen-types.ts +18 -0
- package/src/routing/codegen.ts +50 -10
- package/src/routing/collision-probe.ts +438 -0
- package/src/routing/collision-spaces.ts +281 -0
- package/src/routing/interception.ts +896 -50
- package/src/routing/manifest-codegen.ts +6 -9
- package/src/routing/scanner.ts +114 -113
- package/src/routing/segment-classify.ts +57 -0
- package/src/routing/segment-keys.ts +146 -0
- package/src/routing/slot-placement.ts +97 -0
- package/src/routing/types.ts +1 -3
- package/src/routing/walkers.ts +8 -0
- package/src/search-params/define.ts +6 -29
- package/src/segment-params/define.ts +4 -27
- package/src/server/action-handler.ts +3 -1
- package/src/server/actions.ts +6 -3
- package/src/server/als-registry.ts +2 -1
- package/src/server/build-manifest.ts +14 -1
- package/src/server/chain-url-parts.ts +163 -0
- package/src/server/children-interception.ts +115 -0
- package/src/server/default-status-page.ts +127 -0
- package/src/server/deny-boundary.ts +5 -31
- package/src/server/deny-renderer.ts +83 -22
- package/src/server/head-response.ts +54 -0
- package/src/server/param-coercion.ts +48 -18
- package/src/server/pipeline-helpers.ts +0 -45
- package/src/server/pipeline-interception.ts +81 -32
- package/src/server/pipeline-outcome.ts +3 -5
- package/src/server/pipeline-phases.ts +68 -16
- package/src/server/pipeline.ts +57 -10
- package/src/server/prebuilt-builder.ts +1 -7
- package/src/server/prebuilt-runtime.ts +4 -4
- package/src/server/primitives.ts +0 -18
- package/src/server/publish-params.ts +42 -0
- package/src/server/request-context.ts +97 -18
- package/src/server/route-element-builder.ts +89 -98
- package/src/server/route-handler.ts +8 -8
- package/src/server/route-matcher.ts +21 -9
- package/src/server/rsc-cache-key-guard.ts +170 -0
- package/src/server/rsc-entry/api-handler.ts +6 -8
- package/src/server/rsc-entry/error-renderer.ts +64 -25
- package/src/server/rsc-entry/helpers.ts +31 -16
- package/src/server/rsc-entry/index.ts +36 -28
- package/src/server/rsc-entry/render-route.ts +12 -7
- package/src/server/rsc-entry/revalidate-renderer.ts +1 -1
- package/src/server/rsc-entry/rsc-payload.ts +14 -25
- package/src/server/rsc-entry/rsc-stream.ts +4 -3
- package/src/server/rsc-entry/ssr-renderer.ts +13 -9
- package/src/server/sitemap-generator.ts +1 -7
- package/src/server/skippable-prefix.ts +92 -0
- package/src/server/slot-interception.ts +168 -0
- package/src/server/slot-resolver.ts +253 -156
- package/src/server/ssr-bridge-types.ts +6 -0
- package/src/server/ssr-entry.ts +12 -4
- package/src/server/ssr-wrappers.tsx +33 -32
- package/src/server/state-tree-diff.ts +14 -55
- package/src/server/static-generator.ts +67 -45
- package/src/server/static-not-found.ts +134 -0
- package/src/server/status-code-resolver.ts +4 -47
- package/src/shared/als-slots.ts +72 -0
- package/src/shared/base-path.ts +80 -0
- package/src/shared/param-value.ts +244 -0
- package/src/shared/payload-root.ts +151 -0
- package/src/shared/rsc-cache-key.ts +269 -0
- package/src/shared/rsc-error-envelope.ts +31 -0
- package/src/shared/rsc-manifest.ts +29 -0
- package/src/shared/rsc-payload-path.ts +45 -0
- package/src/shared/segment-info.ts +60 -0
- package/src/shared/slot-params.ts +111 -0
- package/src/shared/static-platform-files.ts +75 -0
- package/src/shims/navigation-client.ts +8 -26
- package/src/shims/navigation.ts +0 -4
- package/dist/_chunks/build-output-helper-DOGYFb_X.js +0 -196
- package/dist/_chunks/build-output-helper-DOGYFb_X.js.map +0 -1
- package/dist/_chunks/canonicalize-DQHyFClh.js.map +0 -1
- package/dist/_chunks/cli-schema-sync-D3naS3eH.js +0 -688
- package/dist/_chunks/cli-schema-sync-D3naS3eH.js.map +0 -1
- package/dist/_chunks/define-COtkxMRT.js +0 -191
- package/dist/_chunks/define-COtkxMRT.js.map +0 -1
- package/dist/_chunks/define-c4au4I9R.js +0 -82
- package/dist/_chunks/define-c4au4I9R.js.map +0 -1
- package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +0 -1
- package/dist/_chunks/logger-AWfuX-KJ.js.map +0 -1
- package/dist/_chunks/navigation-root-bUDZLw74.js +0 -124
- package/dist/_chunks/navigation-root-bUDZLw74.js.map +0 -1
- package/dist/_chunks/plugin-context---kTF5v8.js.map +0 -1
- package/dist/_chunks/router-ref-CtmF-aPv.js.map +0 -1
- package/dist/_chunks/segment-classify-Byy425ng.js.map +0 -1
- package/dist/_chunks/ssr-data-BOWsq18U.js.map +0 -1
- package/dist/_chunks/use-segment-params-D1CzlgBo.js +0 -151
- package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +0 -1
- package/dist/_chunks/walkers-BtTlKviE.js.map +0 -1
- package/dist/client/error-boundary.js.map +0 -1
- package/dist/plugins/request-dep.d.ts +0 -32
- package/dist/plugins/request-dep.d.ts.map +0 -1
- package/src/plugins/request-dep.ts +0 -499
|
@@ -1,499 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* timber-request-dep — Static module-graph analysis for request-dependency.
|
|
3
|
-
*
|
|
4
|
-
* Replaces runtime ALS-based taint tracking with a build/dev-time computed
|
|
5
|
-
* map: segment entry file → statically request-dependent?
|
|
6
|
-
*
|
|
7
|
-
* A segment/slot is request-dependent iff any module reachable from its
|
|
8
|
-
* layout/page/default in the RSC module graph (stopping at client-reference
|
|
9
|
-
* boundaries) imports and calls a request accessor (getHeaders, cookies,
|
|
10
|
-
* getSearchParams, etc.) or calls .get() on a search-params/cookie
|
|
11
|
-
* definition object.
|
|
12
|
-
*
|
|
13
|
-
* This is deterministic, covers children/barrels/node_modules/Suspense-
|
|
14
|
-
* deferred code, and is computed before any byte is flushed.
|
|
15
|
-
*
|
|
16
|
-
* See design/19-client-navigation.md §"X-Timber-State-Tree Header"
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import type { Plugin } from 'vite';
|
|
20
|
-
import type { PluginContext } from '../plugin-context.js';
|
|
21
|
-
import {
|
|
22
|
-
findImportBindings,
|
|
23
|
-
type ProgramNode,
|
|
24
|
-
type CallExpressionNode,
|
|
25
|
-
type MemberExpressionNode,
|
|
26
|
-
type IdentifierNode,
|
|
27
|
-
} from './callsite-ast.js';
|
|
28
|
-
|
|
29
|
-
// ─── Module specifiers whose bindings are request accessors ──────────────
|
|
30
|
-
|
|
31
|
-
const ACCESSOR_SOURCES = new Set(['@timber-js/app/server', 'next/headers', 'next/headers.js']);
|
|
32
|
-
|
|
33
|
-
const ACCESSOR_NAMES = new Set([
|
|
34
|
-
'getHeaders',
|
|
35
|
-
'getHeader',
|
|
36
|
-
'getSearchParams',
|
|
37
|
-
'getCookieJar',
|
|
38
|
-
'getCookie',
|
|
39
|
-
// next/headers shim names
|
|
40
|
-
'headers',
|
|
41
|
-
'cookies',
|
|
42
|
-
]);
|
|
43
|
-
|
|
44
|
-
const DEFINITION_FACTORY_SOURCES = new Set([
|
|
45
|
-
'@timber-js/app/search-params',
|
|
46
|
-
'@timber-js/app/cookies',
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
const DEFINITION_FACTORY_NAMES = new Set(['defineSearchParams', 'defineCookie']);
|
|
50
|
-
|
|
51
|
-
// ─── Framework module detection ─────────────────────────────────────────
|
|
52
|
-
|
|
53
|
-
export function isFrameworkModule(id: string): boolean {
|
|
54
|
-
return (
|
|
55
|
-
/[\\/]node_modules[\\/]@timber-js[\\/]app[\\/]/.test(id) ||
|
|
56
|
-
/[\\/]packages[\\/]timber-app[\\/]src[\\/]/.test(id)
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ─── Fast token pre-filter ───────────────────────────────────────────────
|
|
61
|
-
|
|
62
|
-
const ACCESSOR_TOKENS = [
|
|
63
|
-
'getHeaders',
|
|
64
|
-
'getHeader',
|
|
65
|
-
'getSearchParams',
|
|
66
|
-
'getCookieJar',
|
|
67
|
-
'getCookie',
|
|
68
|
-
'headers',
|
|
69
|
-
'cookies',
|
|
70
|
-
'defineSearchParams',
|
|
71
|
-
'defineCookie',
|
|
72
|
-
// .get() on imported/local definition bindings (searchParams.get())
|
|
73
|
-
'.get(',
|
|
74
|
-
];
|
|
75
|
-
|
|
76
|
-
function hasRelevantToken(code: string): boolean {
|
|
77
|
-
for (const token of ACCESSOR_TOKENS) {
|
|
78
|
-
if (code.includes(token)) return true;
|
|
79
|
-
}
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// ─── Per-module facts ────────────────────────────────────────────────────
|
|
84
|
-
|
|
85
|
-
export interface ModuleFacts {
|
|
86
|
-
/** Module directly calls a request accessor. */
|
|
87
|
-
callsAccessor: boolean;
|
|
88
|
-
/** Module imports a definition factory (defineSearchParams/defineCookie). */
|
|
89
|
-
importsDefinitionFactory: boolean;
|
|
90
|
-
/** Import specifiers where `.get()` was called on the binding. */
|
|
91
|
-
getterCallSources: string[];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// ─── AST analysis ────────────────────────────────────────────────────────
|
|
95
|
-
|
|
96
|
-
export function analyzeModule(code: string, program: ProgramNode): ModuleFacts {
|
|
97
|
-
const facts: ModuleFacts = {
|
|
98
|
-
callsAccessor: false,
|
|
99
|
-
importsDefinitionFactory: false,
|
|
100
|
-
getterCallSources: [],
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// Check for accessor imports
|
|
104
|
-
for (const name of ACCESSOR_NAMES) {
|
|
105
|
-
const bindings = findImportBindings(program, ACCESSOR_SOURCES, name);
|
|
106
|
-
if (bindings.named.size > 0 || bindings.namespaces.size > 0) {
|
|
107
|
-
// Check if any binding is actually called (not just imported)
|
|
108
|
-
if (hasCallSite(program, bindings.named, bindings.namespaces, name)) {
|
|
109
|
-
facts.callsAccessor = true;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Check for definition factory imports
|
|
115
|
-
for (const name of DEFINITION_FACTORY_NAMES) {
|
|
116
|
-
const bindings = findImportBindings(program, DEFINITION_FACTORY_SOURCES, name);
|
|
117
|
-
if (bindings.named.size > 0 || bindings.namespaces.size > 0) {
|
|
118
|
-
facts.importsDefinitionFactory = true;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Check for .get() calls on imported bindings (searchParams.get(), etc.)
|
|
123
|
-
// Collect which import sources have .get() called on their bindings.
|
|
124
|
-
for (const stmt of program.body) {
|
|
125
|
-
if (stmt.type !== 'ImportDeclaration') continue;
|
|
126
|
-
const decl = stmt as unknown as {
|
|
127
|
-
source: { value: string };
|
|
128
|
-
specifiers: Array<{ type: string; local: IdentifierNode; imported?: IdentifierNode }>;
|
|
129
|
-
};
|
|
130
|
-
for (const spec of decl.specifiers) {
|
|
131
|
-
if (spec.type === 'ImportDefaultSpecifier' || spec.type === 'ImportSpecifier') {
|
|
132
|
-
const localName = spec.local.name;
|
|
133
|
-
if (hasGetterCall(program, localName)) {
|
|
134
|
-
facts.getterCallSources.push(decl.source.value);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Check for co-located definitions: const sp = defineSearchParams(...); sp.get()
|
|
141
|
-
// If a module both mints a definition AND calls .get() on any local binding
|
|
142
|
-
// whose init is a defineSearchParams/defineCookie call, it's a taint source.
|
|
143
|
-
if (facts.importsDefinitionFactory) {
|
|
144
|
-
for (const stmt of program.body) {
|
|
145
|
-
if (stmt.type !== 'VariableDeclaration') continue;
|
|
146
|
-
for (const decl of ((stmt as Record<string, unknown>).declarations as Array<
|
|
147
|
-
Record<string, unknown>
|
|
148
|
-
>) ?? []) {
|
|
149
|
-
if (!decl.init || !decl.id) continue;
|
|
150
|
-
const init = decl.init as Record<string, unknown>;
|
|
151
|
-
// Check if init is a call to a definition factory
|
|
152
|
-
if (init.type === 'CallExpression') {
|
|
153
|
-
const callee = init.callee as Record<string, unknown>;
|
|
154
|
-
if (callee.type === 'Identifier') {
|
|
155
|
-
const calleeName = (callee as unknown as IdentifierNode).name;
|
|
156
|
-
// Check if this name is a definition factory binding
|
|
157
|
-
for (const factoryName of DEFINITION_FACTORY_NAMES) {
|
|
158
|
-
const bindings = findImportBindings(program, DEFINITION_FACTORY_SOURCES, factoryName);
|
|
159
|
-
if (bindings.named.has(calleeName)) {
|
|
160
|
-
// This local variable is a definition instance
|
|
161
|
-
const localName =
|
|
162
|
-
(decl.id as Record<string, unknown>).type === 'Identifier'
|
|
163
|
-
? (decl.id as unknown as IdentifierNode).name
|
|
164
|
-
: null;
|
|
165
|
-
if (localName && hasGetterCall(program, localName)) {
|
|
166
|
-
facts.callsAccessor = true;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return facts;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** Check if any named/namespace binding is called as a function. */
|
|
180
|
-
function hasCallSite(
|
|
181
|
-
program: ProgramNode,
|
|
182
|
-
named: Set<string>,
|
|
183
|
-
namespaces: Set<string>,
|
|
184
|
-
importedName: string
|
|
185
|
-
): boolean {
|
|
186
|
-
return walkForCall(program, named, namespaces, importedName);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function walkForCall(
|
|
190
|
-
node: Record<string, unknown>,
|
|
191
|
-
named: Set<string>,
|
|
192
|
-
namespaces: Set<string>,
|
|
193
|
-
importedName: string
|
|
194
|
-
): boolean {
|
|
195
|
-
if (node.type === 'CallExpression') {
|
|
196
|
-
const call = node as unknown as CallExpressionNode;
|
|
197
|
-
const callee = call.callee;
|
|
198
|
-
// Direct call: getHeaders()
|
|
199
|
-
if (callee.type === 'Identifier' && named.has((callee as IdentifierNode).name)) {
|
|
200
|
-
return true;
|
|
201
|
-
}
|
|
202
|
-
// Namespace call: ns.getHeaders()
|
|
203
|
-
if (callee.type === 'MemberExpression') {
|
|
204
|
-
const member = callee as MemberExpressionNode;
|
|
205
|
-
if (
|
|
206
|
-
!member.computed &&
|
|
207
|
-
member.object.type === 'Identifier' &&
|
|
208
|
-
namespaces.has((member.object as IdentifierNode).name) &&
|
|
209
|
-
member.property.type === 'Identifier' &&
|
|
210
|
-
(member.property as IdentifierNode).name === importedName
|
|
211
|
-
) {
|
|
212
|
-
return true;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
for (const key of Object.keys(node)) {
|
|
217
|
-
if (key === 'type' || key === 'start' || key === 'end') continue;
|
|
218
|
-
const val = node[key];
|
|
219
|
-
if (val && typeof val === 'object') {
|
|
220
|
-
if (Array.isArray(val)) {
|
|
221
|
-
for (const item of val) {
|
|
222
|
-
if (item && typeof item === 'object' && typeof item.type === 'string') {
|
|
223
|
-
if (walkForCall(item as Record<string, unknown>, named, namespaces, importedName))
|
|
224
|
-
return true;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
} else if (typeof (val as Record<string, unknown>).type === 'string') {
|
|
228
|
-
if (walkForCall(val as Record<string, unknown>, named, namespaces, importedName))
|
|
229
|
-
return true;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return false;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Check if the object chain of a `.get()` call contains `localName`.
|
|
238
|
-
* Walks through MemberExpression objects and CallExpression callees
|
|
239
|
-
* to handle chained patterns like `getFilterCookie(key).get()` or
|
|
240
|
-
* `cookies.theme.get()`.
|
|
241
|
-
*/
|
|
242
|
-
function objectChainContains(node: Record<string, unknown>, name: string): boolean {
|
|
243
|
-
if (node.type === 'Identifier' && (node as unknown as IdentifierNode).name === name) return true;
|
|
244
|
-
if (node.type === 'MemberExpression') {
|
|
245
|
-
return objectChainContains(
|
|
246
|
-
(node as unknown as MemberExpressionNode).object as Record<string, unknown>,
|
|
247
|
-
name
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
if (node.type === 'CallExpression') {
|
|
251
|
-
return objectChainContains(
|
|
252
|
-
(node as unknown as CallExpressionNode).callee as Record<string, unknown>,
|
|
253
|
-
name
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Check if `.get(...)` is called on `localName` anywhere in the module.
|
|
261
|
-
* Handles direct (`localName.get()`), chained call (`localName(args).get()`),
|
|
262
|
-
* and nested member (`localName.prop.get()`) patterns.
|
|
263
|
-
*/
|
|
264
|
-
function hasGetterCall(node: Record<string, unknown>, localName: string): boolean {
|
|
265
|
-
if (node.type === 'CallExpression') {
|
|
266
|
-
const call = node as unknown as CallExpressionNode;
|
|
267
|
-
if (call.callee.type === 'MemberExpression') {
|
|
268
|
-
const member = call.callee as MemberExpressionNode;
|
|
269
|
-
if (
|
|
270
|
-
!member.computed &&
|
|
271
|
-
member.property.type === 'Identifier' &&
|
|
272
|
-
(member.property as IdentifierNode).name === 'get' &&
|
|
273
|
-
objectChainContains(member.object as Record<string, unknown>, localName)
|
|
274
|
-
) {
|
|
275
|
-
return true;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
for (const key of Object.keys(node)) {
|
|
280
|
-
if (key === 'type' || key === 'start' || key === 'end') continue;
|
|
281
|
-
const val = node[key];
|
|
282
|
-
if (val && typeof val === 'object') {
|
|
283
|
-
if (Array.isArray(val)) {
|
|
284
|
-
for (const item of val) {
|
|
285
|
-
if (item && typeof item === 'object' && typeof item.type === 'string') {
|
|
286
|
-
if (hasGetterCall(item as Record<string, unknown>, localName)) return true;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
} else if (typeof (val as Record<string, unknown>).type === 'string') {
|
|
290
|
-
if (hasGetterCall(val as Record<string, unknown>, localName)) return true;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
return false;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// ─── Module graph reachability ───────────────────────────────────────────
|
|
298
|
-
|
|
299
|
-
/** Walk the module graph from an entry, returning true if any taint source is reachable. */
|
|
300
|
-
function isReachableTaintSource(
|
|
301
|
-
entryId: string,
|
|
302
|
-
factsMap: Map<string, ModuleFacts>,
|
|
303
|
-
definitionModules: Set<string>,
|
|
304
|
-
getImports: (id: string) => string[]
|
|
305
|
-
): boolean {
|
|
306
|
-
const visited = new Set<string>();
|
|
307
|
-
const stack = [entryId];
|
|
308
|
-
|
|
309
|
-
while (stack.length > 0) {
|
|
310
|
-
const id = stack.pop()!;
|
|
311
|
-
if (visited.has(id)) continue;
|
|
312
|
-
visited.add(id);
|
|
313
|
-
|
|
314
|
-
const facts = factsMap.get(id);
|
|
315
|
-
if (facts) {
|
|
316
|
-
if (facts.callsAccessor) return true;
|
|
317
|
-
// Check if any .get() call is on a definition module
|
|
318
|
-
for (const source of facts.getterCallSources) {
|
|
319
|
-
// Resolve relative to the module — for now just check if the
|
|
320
|
-
// resolved ID is a definition module.
|
|
321
|
-
// In dev, the getter source is unresolved; we check if any
|
|
322
|
-
// imported module is a definition module by looking at actual imports.
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Check if this module IS a definition module and has .get() callers
|
|
327
|
-
// (handled by the importer's facts)
|
|
328
|
-
|
|
329
|
-
const imports = getImports(id);
|
|
330
|
-
for (const imp of imports) {
|
|
331
|
-
// Stop at client boundaries — 'use client' modules in the RSC graph
|
|
332
|
-
// resolve to generated proxy stubs with no further imports.
|
|
333
|
-
// Also stop at virtual modules (they're framework internals).
|
|
334
|
-
if (!imp.startsWith('\0') && !visited.has(imp)) {
|
|
335
|
-
stack.push(imp);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Second pass: check getter calls against definition modules
|
|
341
|
-
for (const id of visited) {
|
|
342
|
-
const facts = factsMap.get(id);
|
|
343
|
-
if (!facts) continue;
|
|
344
|
-
if (facts.getterCallSources.length === 0) continue;
|
|
345
|
-
// Check if any import of this module is a definition module
|
|
346
|
-
const imports = getImports(id);
|
|
347
|
-
for (const imp of imports) {
|
|
348
|
-
if (definitionModules.has(imp)) {
|
|
349
|
-
// This module imports a definition module and calls .get() on some binding.
|
|
350
|
-
// Conservative: treat it as a taint source.
|
|
351
|
-
return true;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
return false;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// ─── Plugin ──────────────────────────────────────────────────────────────
|
|
360
|
-
|
|
361
|
-
const BRIDGE_KEY = Symbol.for('timber:request-dep');
|
|
362
|
-
|
|
363
|
-
export function timberRequestDep(ctx: PluginContext): Plugin {
|
|
364
|
-
const factsMap = new Map<string, ModuleFacts>();
|
|
365
|
-
const definitionModules = new Set<string>();
|
|
366
|
-
const cache = new Map<string, boolean>();
|
|
367
|
-
|
|
368
|
-
return {
|
|
369
|
-
name: 'timber-request-dep',
|
|
370
|
-
// Only run in RSC environment — that's where server components render.
|
|
371
|
-
applyToEnvironment(env) {
|
|
372
|
-
return env.name === 'rsc';
|
|
373
|
-
},
|
|
374
|
-
|
|
375
|
-
async transform(code, id) {
|
|
376
|
-
// Skip non-JS (include .mdx/.md — compiled to JS by timber-mdx before this runs)
|
|
377
|
-
if (!/\.[mc]?[jt]sx?$/.test(id) && !/\.mdx?$/.test(id)) return;
|
|
378
|
-
// Skip virtual modules
|
|
379
|
-
if (id.startsWith('\0') || id.startsWith('virtual:')) return;
|
|
380
|
-
// Skip framework modules — their internal accessor calls (e.g.,
|
|
381
|
-
// getCookieJar in define-cookie.ts) are implementation details.
|
|
382
|
-
// In dev they're externalized and never reach transform; in prod
|
|
383
|
-
// they would cause false positives (any module importing defineCookie
|
|
384
|
-
// would be tainted). Analysis relies on user-code .get() patterns.
|
|
385
|
-
if (isFrameworkModule(id)) return;
|
|
386
|
-
// Fast token check
|
|
387
|
-
if (!hasRelevantToken(code)) return;
|
|
388
|
-
|
|
389
|
-
const program = (this as unknown as { parse(code: string): ProgramNode }).parse(code);
|
|
390
|
-
const facts = analyzeModule(code, program);
|
|
391
|
-
|
|
392
|
-
if (
|
|
393
|
-
facts.callsAccessor ||
|
|
394
|
-
facts.importsDefinitionFactory ||
|
|
395
|
-
facts.getterCallSources.length > 0
|
|
396
|
-
) {
|
|
397
|
-
factsMap.set(id, facts);
|
|
398
|
-
if (facts.importsDefinitionFactory) {
|
|
399
|
-
definitionModules.add(id);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// No code transform needed — this is analysis only.
|
|
404
|
-
return undefined;
|
|
405
|
-
},
|
|
406
|
-
|
|
407
|
-
configureServer(server) {
|
|
408
|
-
// Register the bridge so runtime can query request-dep status.
|
|
409
|
-
const resolver = (filePath: string): boolean => {
|
|
410
|
-
if (cache.has(filePath)) return cache.get(filePath)!;
|
|
411
|
-
|
|
412
|
-
const rscEnv = server.environments?.rsc;
|
|
413
|
-
if (!rscEnv?.moduleGraph) {
|
|
414
|
-
return true; // Unknown → conservative
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
const getImports = (moduleId: string): string[] => {
|
|
418
|
-
const mod = rscEnv.moduleGraph.getModuleById(moduleId);
|
|
419
|
-
if (!mod) return [];
|
|
420
|
-
const result: string[] = [];
|
|
421
|
-
for (const imp of mod.importedModules) {
|
|
422
|
-
if (imp.id) result.push(imp.id);
|
|
423
|
-
}
|
|
424
|
-
return result;
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
const result = isReachableTaintSource(filePath, factsMap, definitionModules, getImports);
|
|
428
|
-
cache.set(filePath, result);
|
|
429
|
-
return result;
|
|
430
|
-
};
|
|
431
|
-
|
|
432
|
-
(globalThis as Record<symbol, unknown>)[BRIDGE_KEY] = resolver;
|
|
433
|
-
|
|
434
|
-
// Clear cache on file changes
|
|
435
|
-
const clearCache = () => cache.clear();
|
|
436
|
-
server.watcher.on('change', clearCache);
|
|
437
|
-
server.watcher.on('add', clearCache);
|
|
438
|
-
server.watcher.on('unlink', clearCache);
|
|
439
|
-
},
|
|
440
|
-
|
|
441
|
-
buildEnd() {
|
|
442
|
-
// Prod: compute the full map and register on globalThis for the
|
|
443
|
-
// build manifest plugin to pick up.
|
|
444
|
-
if (ctx.dev) return;
|
|
445
|
-
|
|
446
|
-
const getModuleInfo = (
|
|
447
|
-
this as unknown as {
|
|
448
|
-
getModuleInfo: (
|
|
449
|
-
id: string
|
|
450
|
-
) => { importedIds?: string[]; dynamicallyImportedIds?: string[] } | null;
|
|
451
|
-
}
|
|
452
|
-
).getModuleInfo;
|
|
453
|
-
|
|
454
|
-
const getImports = (moduleId: string): string[] => {
|
|
455
|
-
const info = getModuleInfo(moduleId);
|
|
456
|
-
if (!info) return [];
|
|
457
|
-
return [...(info.importedIds ?? []), ...(info.dynamicallyImportedIds ?? [])];
|
|
458
|
-
};
|
|
459
|
-
|
|
460
|
-
const requestDepMap: Record<string, boolean> = {};
|
|
461
|
-
|
|
462
|
-
// Walk the route tree to find all segment entry files
|
|
463
|
-
if (ctx.routeTree) {
|
|
464
|
-
walkSegmentTree(ctx.routeTree.root as unknown as WalkableNode, (filePath: string) => {
|
|
465
|
-
const result = isReachableTaintSource(filePath, factsMap, definitionModules, getImports);
|
|
466
|
-
requestDepMap[filePath] = result;
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// Store on ctx for build-manifest plugin to serialize into the manifest.
|
|
471
|
-
// Prod runtime reads from __TIMBER_BUILD_MANIFEST__.requestDep.
|
|
472
|
-
(ctx as unknown as Record<string, unknown>).requestDepMap = requestDepMap;
|
|
473
|
-
},
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
interface WalkableNode {
|
|
478
|
-
layout?: { filePath: string };
|
|
479
|
-
page?: { filePath: string };
|
|
480
|
-
default?: { filePath: string };
|
|
481
|
-
children?: unknown[];
|
|
482
|
-
slots?: Record<string, unknown>;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
function walkSegmentTree(node: WalkableNode, fn: (filePath: string) => void): void {
|
|
486
|
-
if (node.layout) fn(node.layout.filePath);
|
|
487
|
-
if (node.page) fn(node.page.filePath);
|
|
488
|
-
if (node.default) fn((node.default as { filePath: string }).filePath);
|
|
489
|
-
if (node.children) {
|
|
490
|
-
for (const child of node.children) {
|
|
491
|
-
walkSegmentTree(child as typeof node, fn);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
if (node.slots) {
|
|
495
|
-
for (const slot of Object.values(node.slots)) {
|
|
496
|
-
walkSegmentTree(slot as typeof node, fn);
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
}
|