@timber-js/app 0.2.0-alpha.16 → 0.2.0-alpha.161
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/agent-skill.md +344 -0
- package/dist/_chunks/actions-cjklt63G.js +317 -0
- package/dist/_chunks/actions-cjklt63G.js.map +1 -0
- package/dist/_chunks/build-output-helper-DF5uScqS.js +158 -0
- package/dist/_chunks/build-output-helper-DF5uScqS.js.map +1 -0
- package/dist/_chunks/cache-api-CzYUlgXA.js +1125 -0
- package/dist/_chunks/cache-api-CzYUlgXA.js.map +1 -0
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → canonicalize-P41GR6tY.js} +94 -18
- package/dist/_chunks/canonicalize-P41GR6tY.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-NfLbLnDw.js +638 -0
- package/dist/_chunks/cli-schema-sync-NfLbLnDw.js.map +1 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
- package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
- package/dist/_chunks/define-Bssfp6ot.js +82 -0
- package/dist/_chunks/define-Bssfp6ot.js.map +1 -0
- package/dist/_chunks/define-CFmvb4Bt.js +203 -0
- package/dist/_chunks/define-CFmvb4Bt.js.map +1 -0
- package/dist/_chunks/dist-BA3u1z3W.js +423 -0
- package/dist/_chunks/dist-BA3u1z3W.js.map +1 -0
- package/dist/_chunks/fast-hash-D6hIVt1Y.js +36 -0
- package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +1 -0
- package/dist/_chunks/format-CfwjgPz9.js +14 -0
- package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
- package/dist/_chunks/href-validation-CMc5JRls.js +141 -0
- package/dist/_chunks/href-validation-CMc5JRls.js.map +1 -0
- package/dist/_chunks/logger-B_O6-mdJ.js +1485 -0
- package/dist/_chunks/logger-B_O6-mdJ.js.map +1 -0
- package/dist/_chunks/navigation-root-bUDZLw74.js +124 -0
- package/dist/_chunks/navigation-root-bUDZLw74.js.map +1 -0
- package/dist/_chunks/plugin-context-DeAxFRMq.js +280 -0
- package/dist/_chunks/plugin-context-DeAxFRMq.js.map +1 -0
- package/dist/_chunks/registry-DbJPKoBp.js +20 -0
- package/dist/_chunks/registry-DbJPKoBp.js.map +1 -0
- package/dist/_chunks/resolve-schema-3iUvBV5T.js +50 -0
- package/dist/_chunks/resolve-schema-3iUvBV5T.js.map +1 -0
- package/dist/_chunks/router-ref-CtmF-aPv.js +28 -0
- package/dist/_chunks/router-ref-CtmF-aPv.js.map +1 -0
- package/dist/_chunks/schema-bridge-BY3QLBL7.js +119 -0
- package/dist/_chunks/schema-bridge-BY3QLBL7.js.map +1 -0
- package/dist/_chunks/segment-classify-CDDRVKs7.js +137 -0
- package/dist/_chunks/segment-classify-CDDRVKs7.js.map +1 -0
- package/dist/_chunks/segment-context-ZDnXDkbz.js +34 -0
- package/dist/_chunks/segment-context-ZDnXDkbz.js.map +1 -0
- package/dist/_chunks/sizeof-lXffQ1Vr.js +35 -0
- package/dist/_chunks/sizeof-lXffQ1Vr.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BOWsq18U.js} +1 -1
- package/dist/_chunks/ssr-data-BOWsq18U.js.map +1 -0
- package/dist/_chunks/tree-match-D2l830j2.js +102 -0
- package/dist/_chunks/tree-match-D2l830j2.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-CbeQmext.js} +7 -20
- package/dist/_chunks/use-query-states-CbeQmext.js.map +1 -0
- package/dist/_chunks/use-segment-params-D1CzlgBo.js +151 -0
- package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -0
- package/dist/_chunks/walkers-9mz9T7mb.js +988 -0
- package/dist/_chunks/walkers-9mz9T7mb.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +29 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.d.ts +109 -0
- package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +73 -0
- package/dist/adapters/cloudflare-dev.js.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +117 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +177 -20
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +337 -64
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts +5 -4
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +1 -3
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +144 -152
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +6 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/adapters/types.d.ts +0 -6
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/cache/cache-api.d.ts +26 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +33 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +27 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +3 -326
- package/dist/cache/invalidation-epoch.d.ts +43 -0
- package/dist/cache/invalidation-epoch.d.ts.map +1 -0
- package/dist/cache/redis-handler.d.ts +97 -8
- package/dist/cache/redis-handler.d.ts.map +1 -1
- package/dist/cache/singleflight.d.ts +19 -2
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/sizeof.d.ts +22 -0
- package/dist/cache/sizeof.d.ts.map +1 -0
- package/dist/cache/stable-stringify.d.ts +9 -0
- package/dist/cache/stable-stringify.d.ts.map +1 -1
- package/dist/cache/store.d.ts +53 -0
- package/dist/cache/store.d.ts.map +1 -0
- package/dist/cache/stores/cloudflare-kv.d.ts +38 -0
- package/dist/cache/stores/cloudflare-kv.d.ts.map +1 -0
- package/dist/cache/stores/cloudflare-kv.js +29 -0
- package/dist/cache/stores/cloudflare-kv.js.map +1 -0
- package/dist/cache/stores/memory.d.ts +42 -0
- package/dist/cache/stores/memory.d.ts.map +1 -0
- package/dist/cache/stores/memory.js +90 -0
- package/dist/cache/stores/memory.js.map +1 -0
- package/dist/cache/stores/redis.d.ts +69 -0
- package/dist/cache/stores/redis.d.ts.map +1 -0
- package/dist/cache/stores/redis.js +35 -0
- package/dist/cache/stores/redis.js.map +1 -0
- package/dist/cache/stores/vercel.d.ts +36 -0
- package/dist/cache/stores/vercel.d.ts.map +1 -0
- package/dist/cache/stores/vercel.js +33 -0
- package/dist/cache/stores/vercel.js.map +1 -0
- package/dist/cache/tag-aware-handler.d.ts +51 -0
- package/dist/cache/tag-aware-handler.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +20 -10
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cdn/cloudflare-purge.d.ts +23 -0
- package/dist/cdn/cloudflare-purge.d.ts.map +1 -0
- package/dist/cdn/fastly-purge.d.ts +25 -0
- package/dist/cdn/fastly-purge.d.ts.map +1 -0
- package/dist/cdn/headers.d.ts +97 -0
- package/dist/cdn/headers.d.ts.map +1 -0
- package/dist/cdn/index.d.ts +5 -0
- package/dist/cdn/index.d.ts.map +1 -0
- package/dist/cdn/purge-store.d.ts +23 -0
- package/dist/cdn/purge-store.d.ts.map +1 -0
- package/dist/cdn/workers-cache-purge.d.ts +16 -0
- package/dist/cdn/workers-cache-purge.d.ts.map +1 -0
- package/dist/cli-schema-sync.d.ts +59 -0
- package/dist/cli-schema-sync.d.ts.map +1 -0
- package/dist/cli.d.ts +34 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +107 -33
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +37 -1
- package/dist/client/browser-dev.d.ts.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
- package/dist/client/browser-entry/hmr.d.ts +21 -0
- package/dist/client/browser-entry/hmr.d.ts.map +1 -0
- package/dist/client/browser-entry/hydrate.d.ts +46 -0
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
- package/dist/client/browser-entry/index.d.ts +29 -0
- package/dist/client/browser-entry/index.d.ts.map +1 -0
- package/dist/client/browser-entry/post-hydration.d.ts +26 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +26 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
- package/dist/client/browser-entry/scroll.d.ts +28 -0
- package/dist/client/browser-entry/scroll.d.ts.map +1 -0
- package/dist/client/child-segment-context.d.ts +22 -0
- package/dist/client/child-segment-context.d.ts.map +1 -0
- package/dist/client/child-segment-outlet.d.ts +18 -0
- package/dist/client/child-segment-outlet.d.ts.map +1 -0
- package/dist/client/child-segment-provider.d.ts +21 -0
- package/dist/client/child-segment-provider.d.ts.map +1 -0
- package/dist/client/error-boundary.d.ts +12 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +47 -10
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/error-reconstituter.d.ts +61 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +16 -27
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +11 -6
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +10 -24
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +182 -1134
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +19 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +825 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link.d.ts +69 -60
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-api.d.ts +120 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +3 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/navigation-root.d.ts +119 -0
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts +1 -1
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/router.d.ts +87 -14
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +47 -14
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +4 -4
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +49 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/segment-update-context.d.ts +21 -0
- package/dist/client/segment-update-context.d.ts.map +1 -0
- package/dist/client/shallow-url.d.ts +10 -0
- package/dist/client/shallow-url.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +13 -4
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/state.d.ts +1 -1
- package/dist/client/top-loader.d.ts +5 -5
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-cookie.d.ts +12 -0
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/client/use-link-status.d.ts +5 -5
- package/dist/client/use-link-status.d.ts.map +1 -1
- package/dist/client/use-pathname.d.ts.map +1 -1
- package/dist/client/use-pending-navigation.d.ts +23 -0
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/client/use-router.d.ts.map +1 -1
- package/dist/client/use-search-params.d.ts +12 -5
- package/dist/client/use-search-params.d.ts.map +1 -1
- package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
- package/dist/client/use-segment-params.d.ts.map +1 -0
- package/dist/codec.d.ts +69 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +75 -0
- package/dist/codec.js.map +1 -0
- package/dist/config-types.d.ts +304 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/config-validation.d.ts +51 -0
- package/dist/config-validation.d.ts.map +1 -0
- package/dist/content/index.d.ts +1 -10
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +0 -2
- package/dist/cookies/define-cookie.d.ts +58 -25
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.d.ts +2 -1
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +257 -36
- package/dist/cookies/index.js.map +1 -1
- package/dist/cookies/json-cookie.d.ts +64 -0
- package/dist/cookies/json-cookie.d.ts.map +1 -0
- package/dist/cookies/validation.d.ts +34 -0
- package/dist/cookies/validation.d.ts.map +1 -0
- package/dist/dev-tools/404-page.d.ts +50 -0
- package/dist/dev-tools/404-page.d.ts.map +1 -0
- package/dist/dev-tools/browser-logs.d.ts +40 -0
- package/dist/dev-tools/browser-logs.d.ts.map +1 -0
- package/dist/dev-tools/dev-page-shell.d.ts +78 -0
- package/dist/dev-tools/dev-page-shell.d.ts.map +1 -0
- package/dist/dev-tools/error-page.d.ts +32 -0
- package/dist/dev-tools/error-page.d.ts.map +1 -0
- package/dist/dev-tools/holding-server.d.ts +54 -0
- package/dist/dev-tools/holding-server.d.ts.map +1 -0
- package/dist/dev-tools/hydration-overlay.d.ts +11 -0
- package/dist/dev-tools/hydration-overlay.d.ts.map +1 -0
- package/dist/dev-tools/index.d.ts +31 -0
- package/dist/dev-tools/index.d.ts.map +1 -0
- package/dist/dev-tools/instrumentation.d.ts +59 -0
- package/dist/dev-tools/instrumentation.d.ts.map +1 -0
- package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
- package/dist/dev-tools/logger.d.ts.map +1 -0
- package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +2 -2
- package/dist/dev-tools/logs.d.ts.map +1 -0
- package/dist/dev-tools/overlay.d.ts +91 -0
- package/dist/dev-tools/overlay.d.ts.map +1 -0
- package/dist/dev-tools/stack-classifier.d.ts +34 -0
- package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
- package/dist/dev-tools/terminal.d.ts +28 -0
- package/dist/dev-tools/terminal.d.ts.map +1 -0
- package/dist/fonts/ast-walk.d.ts +68 -0
- package/dist/fonts/ast-walk.d.ts.map +1 -0
- package/dist/fonts/ast.d.ts +110 -6
- package/dist/fonts/ast.d.ts.map +1 -1
- package/dist/fonts/bundle.d.ts +50 -0
- package/dist/fonts/bundle.d.ts.map +1 -0
- package/dist/fonts/dev-middleware.d.ts +22 -0
- package/dist/fonts/dev-middleware.d.ts.map +1 -0
- package/dist/fonts/fallbacks.d.ts +0 -7
- package/dist/fonts/fallbacks.d.ts.map +1 -1
- package/dist/fonts/google.d.ts +4 -2
- package/dist/fonts/google.d.ts.map +1 -1
- package/dist/fonts/local.d.ts +4 -4
- package/dist/fonts/local.d.ts.map +1 -1
- package/dist/fonts/paths.d.ts +43 -0
- package/dist/fonts/paths.d.ts.map +1 -0
- package/dist/fonts/pipeline.d.ts +158 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +82 -0
- package/dist/fonts/transform.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +47 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +77 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.d.ts +46 -180
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8471 -14108
- package/dist/index.js.map +1 -1
- package/dist/params/codec-registry.d.ts +26 -0
- package/dist/params/codec-registry.d.ts.map +1 -0
- package/dist/params/define-schema.d.ts +81 -0
- package/dist/params/define-schema.d.ts.map +1 -0
- package/dist/params/index.d.ts +5 -0
- package/dist/params/index.d.ts.map +1 -0
- package/dist/params/index.js +34 -0
- package/dist/params/index.js.map +1 -0
- package/dist/params/resolve-schema.d.ts +34 -0
- package/dist/params/resolve-schema.d.ts.map +1 -0
- package/dist/plugin-context.d.ts +190 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +20 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +7 -3
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +43 -7
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/cache.d.ts +64 -0
- package/dist/plugins/cache.d.ts.map +1 -0
- package/dist/plugins/callsite-ast.d.ts +117 -0
- package/dist/plugins/callsite-ast.d.ts.map +1 -0
- package/dist/plugins/callsite-jsx.d.ts +35 -0
- package/dist/plugins/callsite-jsx.d.ts.map +1 -0
- package/dist/plugins/chunks.d.ts +11 -4
- package/dist/plugins/chunks.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +40 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/cloudflare-wasm.d.ts +21 -0
- package/dist/plugins/cloudflare-wasm.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-server.d.ts +17 -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 +16 -73
- 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/prebuilt-capture.d.ts +60 -0
- package/dist/plugins/prebuilt-capture.d.ts.map +1 -0
- package/dist/plugins/prebuilt.d.ts +82 -0
- package/dist/plugins/prebuilt.d.ts.map +1 -0
- package/dist/plugins/prerender-sugar.d.ts +42 -0
- package/dist/plugins/prerender-sugar.d.ts.map +1 -0
- 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 +29 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +5 -26
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +67 -0
- package/dist/routing/codegen-shared.d.ts.map +1 -0
- package/dist/routing/codegen-types.d.ts +64 -0
- package/dist/routing/codegen-types.d.ts.map +1 -0
- package/dist/routing/codegen.d.ts +7 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts +41 -0
- package/dist/routing/convention-lint.d.ts.map +1 -0
- package/dist/routing/export-detect.d.ts +56 -0
- package/dist/routing/export-detect.d.ts.map +1 -0
- package/dist/routing/file-cache.d.ts +8 -0
- package/dist/routing/file-cache.d.ts.map +1 -0
- package/dist/routing/index.d.ts +7 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +4 -2
- package/dist/routing/interception.d.ts +0 -5
- package/dist/routing/interception.d.ts.map +1 -1
- package/dist/routing/link-codegen.d.ts +90 -0
- package/dist/routing/link-codegen.d.ts.map +1 -0
- package/dist/routing/manifest-codegen.d.ts +32 -0
- package/dist/routing/manifest-codegen.d.ts.map +1 -0
- package/dist/routing/scanner.d.ts +1 -10
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/schema-validation.d.ts +35 -0
- package/dist/routing/schema-validation.d.ts.map +1 -0
- package/dist/routing/segment-classify.d.ts +75 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/segment-codegen.d.ts +38 -0
- package/dist/routing/segment-codegen.d.ts.map +1 -0
- package/dist/routing/types.d.ts +77 -25
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/walkers.d.ts +51 -0
- package/dist/routing/walkers.d.ts.map +1 -0
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +12 -0
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +91 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +157 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -7
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +37 -440
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/registry.d.ts +2 -2
- package/dist/search-params/registry.d.ts.map +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/segment-params/define.d.ts +89 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +3 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +2 -0
- package/dist/server/access-gate.d.ts +8 -3
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +41 -6
- 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 +35 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +6 -30
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +86 -11
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/asset-headers.d.ts +8 -18
- package/dist/server/asset-headers.d.ts.map +1 -1
- package/dist/server/body-limits.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +6 -29
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/canonicalize.d.ts +10 -0
- package/dist/server/canonicalize.d.ts.map +1 -1
- package/dist/server/coalesce-tick.d.ts +40 -0
- package/dist/server/coalesce-tick.d.ts.map +1 -0
- package/dist/server/cookie-context.d.ts +170 -0
- package/dist/server/cookie-context.d.ts.map +1 -0
- package/dist/server/cookie-parsing.d.ts +65 -0
- package/dist/server/cookie-parsing.d.ts.map +1 -0
- package/dist/server/csrf.d.ts +3 -2
- package/dist/server/csrf.d.ts.map +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-boundary.d.ts +115 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts +2 -2
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-source-map.d.ts +22 -0
- package/dist/server/dev-source-map.d.ts.map +1 -0
- package/dist/server/early-hints-sender.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -11
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +12 -7
- 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/form-data.d.ts +41 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injector-core.d.ts +221 -0
- package/dist/server/html-injector-core.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +82 -41
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +11 -47
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +170 -2911
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +49 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +3652 -0
- package/dist/server/internal.js.map +1 -0
- package/dist/server/logger.d.ts +39 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/metadata-routes.d.ts +23 -7
- package/dist/server/metadata-routes.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +36 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +119 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/param-coercion.d.ts +54 -0
- package/dist/server/param-coercion.d.ts.map +1 -0
- package/dist/server/pipeline-helpers.d.ts +95 -0
- package/dist/server/pipeline-helpers.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +1 -1
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-metadata.d.ts +6 -0
- package/dist/server/pipeline-metadata.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts +49 -0
- package/dist/server/pipeline-outcome.d.ts.map +1 -0
- package/dist/server/pipeline-phases.d.ts +56 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +122 -19
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/port-resolution.d.ts +117 -0
- package/dist/server/port-resolution.d.ts.map +1 -0
- package/dist/server/prebuilt/cache-key.d.ts +58 -0
- package/dist/server/prebuilt/cache-key.d.ts.map +1 -0
- package/dist/server/prebuilt/capture-state.d.ts +57 -0
- package/dist/server/prebuilt/capture-state.d.ts.map +1 -0
- package/dist/server/prebuilt/manifest-tag-index.d.ts +27 -0
- package/dist/server/prebuilt/manifest-tag-index.d.ts.map +1 -0
- package/dist/server/prebuilt/overlay.d.ts +100 -0
- package/dist/server/prebuilt/overlay.d.ts.map +1 -0
- package/dist/server/prebuilt/payload-source.d.ts +78 -0
- package/dist/server/prebuilt/payload-source.d.ts.map +1 -0
- package/dist/server/prebuilt/synthetic-store.d.ts +66 -0
- package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -0
- package/dist/server/prebuilt-builder.d.ts +120 -0
- package/dist/server/prebuilt-builder.d.ts.map +1 -0
- package/dist/server/prebuilt-runtime.d.ts +101 -0
- package/dist/server/prebuilt-runtime.d.ts.map +1 -0
- package/dist/server/primitives.d.ts +88 -43
- 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/render-utils.d.ts +25 -0
- package/dist/server/render-utils.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +62 -107
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +46 -25
- 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 +25 -36
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
- package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
- package/dist/server/rsc-entry/api-handler.d.ts +12 -3
- 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 +51 -28
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +28 -6
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +50 -0
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
- package/dist/server/rsc-entry/rsc-payload.d.ts +5 -6
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +17 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +5 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +34 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -0
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sensitive-fields.d.ts +74 -0
- package/dist/server/sensitive-fields.d.ts.map +1 -0
- package/dist/server/sitemap-generator.d.ts +129 -0
- package/dist/server/sitemap-generator.d.ts.map +1 -0
- package/dist/server/sitemap-handler.d.ts +22 -0
- package/dist/server/sitemap-handler.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +7 -5
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +121 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -0
- package/dist/server/ssr-entry.d.ts +2 -43
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +64 -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/state-tree-diff.d.ts +12 -5
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/status-code-resolver.d.ts +22 -11
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +47 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +44 -9
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +62 -30
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/tree-match.d.ts +49 -0
- package/dist/server/tree-match.d.ts.map +1 -0
- package/dist/server/types.d.ts +71 -6
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/utils/escape-html.d.ts +14 -0
- package/dist/server/utils/escape-html.d.ts.map +1 -0
- package/dist/server/utils/mdx-file.d.ts +15 -0
- package/dist/server/utils/mdx-file.d.ts.map +1 -0
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/server/workers-cache-bridge.d.ts +26 -0
- package/dist/server/workers-cache-bridge.d.ts.map +1 -0
- package/dist/shared/href-validation.d.ts +49 -0
- package/dist/shared/href-validation.d.ts.map +1 -0
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shared/redirect-type.d.ts +17 -0
- package/dist/shared/redirect-type.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.js +42 -0
- package/dist/shims/font-google.js.map +1 -0
- package/dist/shims/font-local.d.ts +26 -0
- package/dist/shims/font-local.d.ts.map +1 -0
- package/dist/shims/font-local.js +20 -0
- package/dist/shims/font-local.js.map +1 -0
- package/dist/shims/headers.d.ts +53 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/image.d.ts +16 -16
- package/dist/shims/navigation-client.d.ts +35 -11
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +11 -5
- 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/docs/api/30-api-server.mdx +233 -0
- package/docs/api/31-api-client.mdx +161 -0
- package/docs/api/32-api-cache.mdx +199 -0
- package/docs/api/33-api-search-params.mdx +141 -0
- package/docs/api/34-api-config.mdx +189 -0
- package/docs/api/35-api-typescript.mdx +170 -0
- package/docs/api/36-cli.mdx +143 -0
- package/docs/learn/00-introduction.mdx +76 -0
- package/docs/learn/01-quick-start.mdx +94 -0
- package/docs/learn/02-pages-and-layouts.mdx +147 -0
- package/docs/learn/03-fetching-data.mdx +211 -0
- package/docs/learn/03b-access-control.mdx +130 -0
- package/docs/learn/04-loading-states.mdx +67 -0
- package/docs/learn/04b-the-flush-point.mdx +115 -0
- package/docs/learn/05-typed-params.mdx +275 -0
- package/docs/learn/06-forms-and-actions.mdx +146 -0
- package/docs/learn/07-typed-routes.mdx +127 -0
- package/docs/learn/08-streaming.mdx +146 -0
- package/docs/learn/09-caching.mdx +136 -0
- package/docs/learn/10-middleware.mdx +157 -0
- package/docs/learn/11-error-handling.mdx +156 -0
- package/docs/learn/12-client-navigation.mdx +168 -0
- package/docs/learn/13-configuration.mdx +145 -0
- package/docs/learn/14-deploying.mdx +264 -0
- package/docs/more/01-advanced-routing.mdx +139 -0
- package/docs/more/02-advanced-forms.mdx +137 -0
- package/docs/more/03-coming-from-nextjs.mdx +186 -0
- package/docs/more/04-metadata-and-fonts.mdx +193 -0
- package/docs/more/04b-mdx.mdx +209 -0
- package/docs/more/05-content-collections.mdx +90 -0
- package/docs/more/06-instrumentation.mdx +214 -0
- package/docs/more/07-security.mdx +129 -0
- package/docs/more/08-developer-experience.mdx +134 -0
- package/docs/more/40-why-timber.mdx +50 -0
- package/docs/more/41-timber-vs-nextjs.mdx +81 -0
- package/docs/more/42-timber-vs-others.mdx +68 -0
- package/docs/more/50-ai-agent-instructions.mdx +169 -0
- package/llms.txt +55 -0
- package/package.json +103 -26
- package/src/adapters/build-output-helper.ts +199 -0
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +179 -0
- package/src/adapters/cloudflare.ts +571 -118
- package/src/adapters/compress-module.ts +27 -92
- package/src/adapters/nitro.ts +131 -107
- package/src/adapters/raw-imports.d.ts +5 -0
- package/src/adapters/shared.ts +68 -0
- package/src/adapters/types.ts +0 -7
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +107 -0
- package/src/cache/handler-store.ts +76 -0
- package/src/cache/index.ts +88 -18
- package/src/cache/invalidation-epoch.ts +93 -0
- package/src/cache/redis-handler.ts +122 -15
- package/src/cache/singleflight.ts +64 -6
- package/src/cache/sizeof.ts +33 -0
- package/src/cache/stable-stringify.ts +65 -2
- package/src/cache/store.ts +71 -0
- package/src/cache/stores/cloudflare-kv.ts +52 -0
- package/src/cache/stores/memory.ts +125 -0
- package/src/cache/stores/redis.ts +97 -0
- package/src/cache/stores/vercel.ts +59 -0
- package/src/cache/tag-aware-handler.ts +233 -0
- package/src/cache/timber-cache.ts +142 -36
- package/src/cdn/cloudflare-purge.ts +50 -0
- package/src/cdn/fastly-purge.ts +63 -0
- package/src/cdn/headers.ts +153 -0
- package/src/cdn/index.ts +17 -0
- package/src/cdn/purge-store.ts +34 -0
- package/src/cdn/workers-cache-purge.ts +30 -0
- package/src/cli-schema-sync.ts +388 -0
- package/src/cli.ts +157 -34
- package/src/client/browser-dev.ts +156 -1
- package/src/client/browser-entry/action-dispatch.ts +124 -0
- package/src/client/browser-entry/hmr.ts +70 -0
- package/src/client/browser-entry/hydrate.ts +187 -0
- package/src/client/browser-entry/index.ts +111 -0
- package/src/client/browser-entry/post-hydration.ts +103 -0
- package/src/client/browser-entry/router-init.ts +287 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +50 -0
- package/src/client/child-segment-context.ts +40 -0
- package/src/client/child-segment-outlet.tsx +25 -0
- package/src/client/child-segment-provider.tsx +27 -0
- package/src/client/error-boundary.tsx +127 -22
- package/src/client/error-reconstituter.tsx +79 -0
- package/src/client/form.tsx +31 -32
- package/src/client/history.ts +11 -7
- package/src/client/index.ts +67 -45
- package/src/client/internal.ts +58 -0
- package/src/client/link.tsx +346 -150
- package/src/client/navigation-api.ts +341 -0
- package/src/client/navigation-context.ts +15 -7
- package/src/client/navigation-root.tsx +355 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +482 -166
- package/src/client/rsc-fetch.ts +214 -33
- package/src/client/segment-cache.ts +7 -7
- package/src/client/segment-outlet.tsx +77 -0
- package/src/client/segment-update-context.ts +42 -0
- package/src/client/shallow-url.ts +22 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/state.ts +2 -2
- package/src/client/top-loader.tsx +11 -9
- package/src/client/use-cookie.ts +60 -15
- package/src/client/use-link-status.ts +7 -7
- package/src/client/use-pathname.ts +1 -0
- package/src/client/use-pending-navigation.ts +40 -0
- package/src/client/use-query-states.ts +9 -3
- package/src/client/use-router.ts +4 -1
- package/src/client/use-search-params.ts +31 -44
- package/src/client/{use-params.ts → use-segment-params.ts} +9 -6
- package/src/codec.ts +147 -0
- package/src/config-types.ts +302 -0
- package/src/config-validation.ts +328 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +217 -53
- package/src/cookies/index.ts +12 -1
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +192 -0
- package/src/dev-tools/404-page.ts +286 -0
- package/src/dev-tools/browser-logs.ts +55 -0
- package/src/dev-tools/dev-page-shell.ts +260 -0
- package/src/dev-tools/error-page.ts +331 -0
- package/src/dev-tools/holding-server.ts +187 -0
- package/src/dev-tools/hydration-overlay.ts +158 -0
- package/src/dev-tools/index.ts +83 -0
- package/src/dev-tools/instrumentation.ts +213 -0
- package/src/{server/dev-logger.ts → dev-tools/logger.ts} +33 -51
- package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +9 -5
- package/src/dev-tools/overlay.ts +469 -0
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/dev-tools/terminal.ts +182 -0
- package/src/fonts/ast-walk.ts +235 -0
- package/src/fonts/ast.ts +477 -126
- package/src/fonts/bundle.ts +138 -0
- package/src/fonts/dev-middleware.ts +85 -0
- package/src/fonts/fallbacks.ts +0 -23
- package/src/fonts/google.ts +63 -8
- package/src/fonts/local.ts +9 -8
- package/src/fonts/paths.ts +58 -0
- package/src/fonts/pipeline.ts +316 -0
- package/src/fonts/transform.ts +305 -0
- package/src/fonts/types.ts +52 -1
- package/src/fonts/virtual-modules.ts +179 -0
- package/src/index.ts +431 -352
- package/src/params/codec-registry.ts +34 -0
- package/src/params/define-schema.ts +115 -0
- package/src/params/index.ts +17 -0
- package/src/params/resolve-schema.ts +84 -0
- package/src/plugin-context.ts +378 -0
- package/src/plugins/adapter-build.ts +98 -4
- package/src/plugins/build-manifest.ts +168 -23
- package/src/plugins/build-report.ts +253 -35
- package/src/plugins/cache.ts +229 -0
- package/src/plugins/callsite-ast.ts +472 -0
- package/src/plugins/callsite-jsx.ts +243 -0
- package/src/plugins/chunks.ts +74 -5
- package/src/plugins/client-chunks.ts +144 -0
- package/src/plugins/cloudflare-wasm.ts +141 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +293 -46
- package/src/plugins/entries.ts +129 -8
- package/src/plugins/fonts.ts +199 -664
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/prebuilt-capture.ts +217 -0
- package/src/plugins/prebuilt.ts +700 -0
- package/src/plugins/prerender-sugar.ts +329 -0
- package/src/plugins/routing.ts +237 -241
- package/src/plugins/server-bundle.ts +97 -12
- package/src/plugins/shims.ts +241 -64
- package/src/plugins/static-build.ts +15 -90
- package/src/routing/codegen-shared.ts +115 -0
- package/src/routing/codegen-types.ts +65 -0
- package/src/routing/codegen.ts +360 -178
- package/src/routing/convention-lint.ts +394 -0
- package/src/routing/export-detect.ts +304 -0
- package/src/routing/file-cache.ts +23 -0
- package/src/routing/index.ts +10 -1
- package/src/routing/interception.ts +3 -22
- package/src/routing/link-codegen.ts +310 -0
- package/src/routing/manifest-codegen.ts +281 -0
- package/src/routing/scanner.ts +248 -188
- package/src/routing/schema-validation.ts +149 -0
- package/src/routing/segment-classify.ts +188 -0
- package/src/routing/segment-codegen.ts +98 -0
- package/src/routing/types.ts +78 -25
- package/src/routing/walkers.ts +90 -0
- package/src/rsc-runtime/rsc.ts +9 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/schema-bridge.ts +252 -0
- package/src/search-params/define.ts +570 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +110 -0
- package/src/segment-params/define.ts +249 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +84 -34
- package/src/server/action-client.ts +119 -28
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +123 -33
- package/src/server/actions.ts +48 -54
- package/src/server/als-registry.ts +130 -20
- package/src/server/asset-headers.ts +15 -37
- package/src/server/body-limits.ts +10 -2
- package/src/server/build-manifest.ts +13 -56
- package/src/server/canonicalize.ts +6 -3
- package/src/server/coalesce-tick.ts +75 -0
- package/src/server/compress.ts +34 -7
- package/src/server/cookie-context.ts +484 -0
- package/src/server/cookie-parsing.ts +163 -0
- package/src/server/csrf.ts +39 -6
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-boundary.ts +311 -0
- package/src/server/deny-renderer.ts +85 -77
- package/src/server/dev-source-map.ts +31 -0
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/early-hints.ts +37 -27
- package/src/server/error-boundary-wrapper.ts +61 -22
- package/src/server/fallback-error.ts +79 -102
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/form-data.ts +124 -12
- package/src/server/html-injector-core.ts +437 -0
- package/src/server/html-injectors.ts +267 -254
- package/src/server/index.ts +31 -185
- package/src/server/internal.ts +181 -0
- package/src/server/logger.ts +72 -36
- package/src/server/metadata-routes.ts +44 -19
- package/src/server/middleware-runner.ts +75 -4
- package/src/server/node-stream-transforms.ts +331 -0
- package/src/server/param-coercion.ts +206 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-interception.ts +32 -18
- package/src/server/pipeline-metadata.ts +14 -0
- package/src/server/pipeline-outcome.ts +197 -0
- package/src/server/pipeline-phases.ts +538 -0
- package/src/server/pipeline.ts +226 -382
- package/src/server/port-resolution.ts +215 -0
- package/src/server/prebuilt/cache-key.ts +224 -0
- package/src/server/prebuilt/capture-state.ts +89 -0
- package/src/server/prebuilt/manifest-tag-index.ts +46 -0
- package/src/server/prebuilt/overlay.ts +256 -0
- package/src/server/prebuilt/payload-source.ts +201 -0
- package/src/server/prebuilt/synthetic-store.ts +121 -0
- package/src/server/prebuilt-builder.ts +774 -0
- package/src/server/prebuilt-runtime.ts +731 -0
- package/src/server/primitives.ts +160 -83
- package/src/server/render-timeout.ts +108 -0
- package/src/server/render-utils.ts +31 -0
- package/src/server/request-context.ts +168 -337
- package/src/server/route-element-builder.ts +548 -233
- package/src/server/route-handler.ts +31 -4
- package/src/server/route-matcher.ts +144 -277
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/api-handler.ts +69 -32
- package/src/server/rsc-entry/error-renderer.ts +306 -89
- package/src/server/rsc-entry/helpers.ts +160 -76
- package/src/server/rsc-entry/index.ts +394 -330
- package/src/server/rsc-entry/render-route.ts +288 -0
- package/src/server/rsc-entry/revalidate-renderer.ts +349 -0
- package/src/server/rsc-entry/rsc-payload.ts +74 -35
- package/src/server/rsc-entry/rsc-stream.ts +85 -13
- package/src/server/rsc-entry/ssr-bridge.ts +18 -5
- package/src/server/rsc-entry/ssr-renderer.ts +273 -43
- package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
- package/src/server/safe-load.ts +60 -0
- package/src/server/sensitive-fields.ts +230 -0
- package/src/server/server-only-guard-noop.js +3 -0
- package/src/server/sitemap-generator.ts +344 -0
- package/src/server/sitemap-handler.ts +157 -0
- package/src/server/slot-resolver.ts +258 -257
- package/src/server/ssr-bridge-types.ts +124 -0
- package/src/server/ssr-entry.ts +206 -78
- package/src/server/ssr-render.ts +345 -82
- package/src/server/ssr-wrappers.tsx +141 -0
- package/src/server/state-tree-diff.ts +30 -23
- package/src/server/status-code-resolver.ts +115 -130
- package/src/server/stream-utils.ts +286 -0
- package/src/server/tracing.ts +126 -14
- package/src/server/tree-builder.ts +204 -90
- package/src/server/tree-match.ts +220 -0
- package/src/server/types.ts +78 -9
- package/src/server/utils/escape-html.ts +20 -0
- package/src/server/utils/mdx-file.ts +22 -0
- package/src/server/version-skew.ts +104 -0
- package/src/server/workers-cache-bridge.ts +33 -0
- package/src/shared/href-validation.ts +159 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shared/redirect-type.ts +17 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/headers.ts +122 -1
- package/src/shims/navigation-client.ts +51 -29
- package/src/shims/navigation.ts +14 -7
- package/src/utils/state-machine.ts +111 -0
- package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-B3Gypr3D.js +0 -108
- package/dist/_chunks/debug-B3Gypr3D.js.map +0 -1
- package/dist/_chunks/format-RyoGQL74.js +0 -164
- package/dist/_chunks/format-RyoGQL74.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js +0 -676
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
- package/dist/_chunks/request-context-BQUC8PHn.js +0 -330
- package/dist/_chunks/request-context-BQUC8PHn.js.map +0 -1
- package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
- package/dist/_chunks/tracing-CemImE6h.js +0 -187
- package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
- package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
- package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/cache/index.js.map +0 -1
- package/dist/cache/register-cached-function.d.ts +0 -17
- package/dist/cache/register-cached-function.d.ts.map +0 -1
- package/dist/client/browser-entry.d.ts +0 -21
- package/dist/client/browser-entry.d.ts.map +0 -1
- package/dist/client/head.d.ts +0 -16
- package/dist/client/head.d.ts.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/segment-merger.d.ts +0 -119
- package/dist/client/segment-merger.d.ts.map +0 -1
- package/dist/client/stale-reload.d.ts +0 -44
- package/dist/client/stale-reload.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts +0 -74
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts +0 -26
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/dist/client/use-params.d.ts.map +0 -1
- package/dist/plugins/cache-transform.d.ts +0 -36
- package/dist/plugins/cache-transform.d.ts.map +0 -1
- package/dist/plugins/dev-error-overlay.d.ts +0 -60
- package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
- package/dist/plugins/dev-logs.d.ts.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.d.ts.map +0 -1
- package/dist/plugins/server-action-exports.d.ts +0 -26
- package/dist/plugins/server-action-exports.d.ts.map +0 -1
- package/dist/routing/status-file-lint.d.ts +0 -33
- package/dist/routing/status-file-lint.d.ts.map +0 -1
- package/dist/search-params/analyze.d.ts +0 -54
- package/dist/search-params/analyze.d.ts.map +0 -1
- package/dist/search-params/builtin-codecs.d.ts +0 -105
- package/dist/search-params/builtin-codecs.d.ts.map +0 -1
- package/dist/search-params/codecs.d.ts +0 -53
- package/dist/search-params/codecs.d.ts.map +0 -1
- package/dist/search-params/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/server/client-module-map.d.ts +0 -47
- package/dist/server/client-module-map.d.ts.map +0 -1
- package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
- package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
- package/dist/server/dev-logger.d.ts.map +0 -1
- package/dist/server/dev-span-processor.d.ts +0 -29
- package/dist/server/dev-span-processor.d.ts.map +0 -1
- package/dist/server/dev-warnings.d.ts +0 -129
- package/dist/server/dev-warnings.d.ts.map +0 -1
- package/dist/server/flush.d.ts +0 -74
- package/dist/server/flush.d.ts.map +0 -1
- package/dist/server/manifest-status-resolver.d.ts +0 -58
- package/dist/server/manifest-status-resolver.d.ts.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/utils/directive-parser.d.ts +0 -70
- package/dist/utils/directive-parser.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -103
- package/src/client/browser-entry.ts +0 -678
- package/src/client/head.ts +0 -61
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/segment-merger.ts +0 -339
- package/src/client/stale-reload.ts +0 -87
- package/src/client/transition-root.tsx +0 -166
- package/src/client/use-navigation-pending.ts +0 -38
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dev-error-overlay.ts +0 -230
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/plugins/server-action-exports.ts +0 -220
- package/src/routing/status-file-lint.ts +0 -112
- package/src/search-params/analyze.ts +0 -192
- package/src/search-params/builtin-codecs.ts +0 -228
- package/src/search-params/codecs.ts +0 -153
- package/src/search-params/create.ts +0 -321
- package/src/server/client-module-map.ts +0 -58
- package/src/server/dev-fetch-instrumentation.ts +0 -96
- package/src/server/dev-span-processor.ts +0 -78
- package/src/server/dev-warnings.ts +0 -283
- package/src/server/flush.ts +0 -182
- package/src/server/manifest-status-resolver.ts +0 -215
- package/src/server/prerender.ts +0 -139
- package/src/utils/directive-parser.ts +0 -529
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Forms and Actions'
|
|
3
|
+
description: 'Server actions with validation, progressive enhancement, and forms that work without JavaScript.'
|
|
4
|
+
slug: 'forms-and-actions'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Forms and Actions
|
|
8
|
+
|
|
9
|
+
Forms in timber.js work without JavaScript. They submit to the server, validate, and return a result. When JavaScript is available, they enhance with client-side state and pending UI.
|
|
10
|
+
|
|
11
|
+
## Action Clients
|
|
12
|
+
|
|
13
|
+
Define reusable action middleware with `createActionClient`:
|
|
14
|
+
|
|
15
|
+
```ts title="lib/action.ts"
|
|
16
|
+
import { createActionClient, ActionError } from '@timber-js/app/server';
|
|
17
|
+
import { getUser } from '@/lib/auth';
|
|
18
|
+
|
|
19
|
+
export const action = createActionClient({
|
|
20
|
+
middleware: async () => {
|
|
21
|
+
const user = await getUser();
|
|
22
|
+
if (!user) throw new ActionError('UNAUTHORIZED');
|
|
23
|
+
return { user };
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Defining Actions
|
|
29
|
+
|
|
30
|
+
```ts title="app/todos/actions.ts"
|
|
31
|
+
'use server';
|
|
32
|
+
|
|
33
|
+
import { z } from 'zod/v4';
|
|
34
|
+
import { action } from '@/lib/action';
|
|
35
|
+
import { revalidatePath } from '@timber-js/app/server';
|
|
36
|
+
|
|
37
|
+
declare const db: { todos: { create(data: { title: string; userId: string }): Promise<void> } };
|
|
38
|
+
|
|
39
|
+
export const createTodo = action
|
|
40
|
+
.schema(z.object({ title: z.string().min(1) }))
|
|
41
|
+
.action(async ({ input, ctx }) => {
|
|
42
|
+
await db.todos.create({ ...input, userId: ctx.user.id });
|
|
43
|
+
return revalidatePath('/todos');
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The `.schema()` method accepts any Standard Schema-compatible validator — Zod, Valibot, or ArkType. Validation errors are returned to the client automatically.
|
|
48
|
+
|
|
49
|
+
## Using Actions in Forms
|
|
50
|
+
|
|
51
|
+
```tsx title="app/todos/todo-form.tsx"
|
|
52
|
+
'use client';
|
|
53
|
+
|
|
54
|
+
import { useActionState } from '@timber-js/app/client';
|
|
55
|
+
import { createTodo } from './actions';
|
|
56
|
+
|
|
57
|
+
export default function TodoForm() {
|
|
58
|
+
const [state, action, pending, errors] = useActionState(createTodo, null);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<form action={action}>
|
|
62
|
+
<div>
|
|
63
|
+
<input name="title" required />
|
|
64
|
+
{errors.getFieldError('title') && (
|
|
65
|
+
<p className="text-red-600">{errors.getFieldError('title')}</p>
|
|
66
|
+
)}
|
|
67
|
+
</div>
|
|
68
|
+
{errors.serverError && (
|
|
69
|
+
<p className="text-red-600">Something went wrong. Please try again.</p>
|
|
70
|
+
)}
|
|
71
|
+
<button type="submit" disabled={pending}>
|
|
72
|
+
{pending ? 'Adding...' : 'Add Todo'}
|
|
73
|
+
</button>
|
|
74
|
+
</form>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Without JS, this submits as a standard form POST. With JS, `useActionState` handles pending state and error display.
|
|
80
|
+
|
|
81
|
+
### Form Errors
|
|
82
|
+
|
|
83
|
+
`useActionState` from `@timber-js/app/client` returns a 4-tuple where the 4th element is auto-derived form errors:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
const [state, action, pending, errors] = useActionState(myAction, null);
|
|
87
|
+
|
|
88
|
+
errors.fieldErrors; // Record<string, string[]>
|
|
89
|
+
errors.formErrors; // string[] (form-level errors)
|
|
90
|
+
errors.serverError; // { code: string; data?: Record<string, unknown> } | null
|
|
91
|
+
errors.hasErrors; // boolean
|
|
92
|
+
errors.getFieldError('title'); // string | null (first error for field)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## After Mutation
|
|
96
|
+
|
|
97
|
+
| Pattern | When to use |
|
|
98
|
+
| ------------------------- | ------------------------------------------------ |
|
|
99
|
+
| `redirect('/path')` | User should land somewhere new |
|
|
100
|
+
| `revalidatePath('/path')` | Current page needs fresh data |
|
|
101
|
+
| `useOptimistic` | Instant UI update, action confirms in background |
|
|
102
|
+
|
|
103
|
+
## Forms Without JavaScript
|
|
104
|
+
|
|
105
|
+
When JavaScript is disabled and a server action returns validation errors, timber re-renders the page instead of redirecting. The errors and submitted values are available via `getFormFlash()`:
|
|
106
|
+
|
|
107
|
+
```tsx title="app/todos/page.tsx"
|
|
108
|
+
import { getFormFlash } from '@timber-js/app/server';
|
|
109
|
+
import { TodoForm } from './todo-form';
|
|
110
|
+
|
|
111
|
+
export default async function TodosPage() {
|
|
112
|
+
const flash = getFormFlash();
|
|
113
|
+
return <TodoForm flash={flash} />;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```tsx title="app/todos/todo-form.tsx"
|
|
118
|
+
'use client';
|
|
119
|
+
|
|
120
|
+
import { useActionState } from '@timber-js/app/client';
|
|
121
|
+
import { createTodo } from './actions';
|
|
122
|
+
import type { FormFlashData } from '@timber-js/app/server';
|
|
123
|
+
|
|
124
|
+
export function TodoForm({ flash }: { flash?: FormFlashData | null }) {
|
|
125
|
+
const [state, action, pending, errors] = useActionState(createTodo, null);
|
|
126
|
+
|
|
127
|
+
const fieldError = (field: string) =>
|
|
128
|
+
errors.getFieldError(field) ?? flash?.validationErrors?.[field]?.[0];
|
|
129
|
+
const defaultValue = (field: string) =>
|
|
130
|
+
(flash?.submittedValues?.[field] as string) ?? '';
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<form action={action}>
|
|
134
|
+
<input name="title" defaultValue={defaultValue('title')} />
|
|
135
|
+
{fieldError('title') && <p className="text-red-600">{fieldError('title')}</p>}
|
|
136
|
+
<button type="submit" disabled={pending}>
|
|
137
|
+
{pending ? 'Adding...' : 'Add Todo'}
|
|
138
|
+
</button>
|
|
139
|
+
</form>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Flash data is server-side only — stored in AsyncLocalStorage for the duration of the re-render. Sensitive fields (password, apiKey, cvv, etc.) are automatically stripped from `submittedValues`.
|
|
145
|
+
|
|
146
|
+
For advanced topics — coercion helpers, `parseFormData`, sensitive field stripping configuration, and the full end-to-end example — see [Advanced Forms](/docs/advanced-forms).
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Typed Routes'
|
|
3
|
+
description: 'Build-time route types — <Link> validates href, params are inferred from the file tree.'
|
|
4
|
+
slug: 'typed-routes'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Typed Routes
|
|
8
|
+
|
|
9
|
+
timber.js generates route types at build time. `<Link>` type-checks `href` against your actual route tree. Segment params are inferred from directory names. Search params are typed when you define them.
|
|
10
|
+
|
|
11
|
+
## How It Works
|
|
12
|
+
|
|
13
|
+
When you run `timber dev` or `timber build`, the framework scans your `app/` directory and generates a route map in `.timber/routes.d.ts`:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// .timber/routes.d.ts (generated, gitignored)
|
|
17
|
+
export interface TimberSegmentParams {
|
|
18
|
+
'/': {};
|
|
19
|
+
'/products/[id]': { id: number };
|
|
20
|
+
'/blog/[...slug]': { slug: string[] };
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Types reference your `app/schema.ts` codecs directly, so they stay in sync automatically.
|
|
25
|
+
|
|
26
|
+
## Typed `<Link>`
|
|
27
|
+
|
|
28
|
+
`<Link>` validates `href` against the route map. Invalid routes are caught at build time:
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { Link } from '@timber-js/app/client';
|
|
32
|
+
|
|
33
|
+
<Link href="/about">About</Link> // ✓ known route
|
|
34
|
+
<Link href="/nonexistent">Bad</Link> // ✗ TypeScript error
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For dynamic routes, pass `segmentParams`:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { Link } from '@timber-js/app/client';
|
|
41
|
+
|
|
42
|
+
<Link href="/products/[id]" segmentParams={{ id: 42 }}>
|
|
43
|
+
Product
|
|
44
|
+
</Link>
|
|
45
|
+
// → <a href="/products/42">Product</a>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or use an interpolated href directly:
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<Link href={`/products/${id}`}>Product</Link>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Both forms are type-safe. With the pattern form (`/products/[id]`), `segmentParams` is required and typed. With the interpolated form, `segmentParams` is forbidden.
|
|
55
|
+
|
|
56
|
+
## Typed Segment Params
|
|
57
|
+
|
|
58
|
+
Each route directory gets a generated `$segment` module. Import `SEGMENT_PATH` for type-safe param access:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
// app/products/[id]/page.tsx
|
|
62
|
+
import { SEGMENT_PATH } from './$segment';
|
|
63
|
+
import { getSegmentParams } from '@timber-js/app/server';
|
|
64
|
+
|
|
65
|
+
export default async function ProductPage() {
|
|
66
|
+
const { id } = getSegmentParams(SEGMENT_PATH);
|
|
67
|
+
// id is typed from your schema codec (e.g., number for codec.integer)
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Without `SEGMENT_PATH`, params are untyped — all optional strings.
|
|
72
|
+
|
|
73
|
+
### tsconfig.json
|
|
74
|
+
|
|
75
|
+
Add `rootDirs` so TypeScript can resolve `$segment` imports:
|
|
76
|
+
|
|
77
|
+
```jsonc
|
|
78
|
+
{
|
|
79
|
+
"compilerOptions": {
|
|
80
|
+
"rootDirs": [".", ".timber/types"]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Typed Search Params
|
|
86
|
+
|
|
87
|
+
When a `params.ts` file exports `searchParams`, search params are fully typed throughout the stack:
|
|
88
|
+
|
|
89
|
+
```ts title="app/products/params.ts"
|
|
90
|
+
import { defineSearchParams, withDefault, withUrlKey } from '@timber-js/app/search-params';
|
|
91
|
+
import { parseAsInteger, parseAsString, parseAsStringEnum } from 'nuqs';
|
|
92
|
+
import { z } from 'zod/v4';
|
|
93
|
+
|
|
94
|
+
export const searchParams = defineSearchParams({
|
|
95
|
+
page: withDefault(parseAsInteger, 1),
|
|
96
|
+
q: withUrlKey(parseAsString, 'search'),
|
|
97
|
+
category: z.string().nullable().default(null),
|
|
98
|
+
sort: withDefault(parseAsStringEnum(['price-asc', 'price-desc', 'newest']), 'newest'),
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```tsx title="app/products/page.tsx"
|
|
103
|
+
import { searchParams } from './params';
|
|
104
|
+
|
|
105
|
+
export default async function ProductsPage() {
|
|
106
|
+
const { page, q, category, sort } = await searchParams.get();
|
|
107
|
+
// page: number, q: string | null, category: string | null, sort: 'price-asc' | ...
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`<Link>` validates `searchParams` against the route's definition too:
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
<Link
|
|
115
|
+
href="/products/[id]"
|
|
116
|
+
segmentParams={{ id }}
|
|
117
|
+
searchParams={{ sort: 'newest', q: 'boots' }}
|
|
118
|
+
/>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
See [Typed Params](/docs/typed-params) for the full search params API.
|
|
122
|
+
|
|
123
|
+
## Codegen
|
|
124
|
+
|
|
125
|
+
Types are generated during `timber dev` (on startup and when routes change) and `timber build`. The generated `.timber/routes.d.ts` is gitignored — it's a build artifact. Run `timber dev` once to get types for your editor.
|
|
126
|
+
|
|
127
|
+
For the full type definitions and context types (`RouteContext`, `MiddlewareContext`, `AccessContext`), see the [TypeScript API Reference](/docs/api-typescript).
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Streaming'
|
|
3
|
+
description: 'Suspense placement, deferSuspenseFor, and the layout footgun.'
|
|
4
|
+
slug: 'streaming'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Streaming
|
|
8
|
+
|
|
9
|
+
```ts title="app/schema.ts" id="schema" hidden
|
|
10
|
+
import { defineSchema } from '@timber-js/app/params';
|
|
11
|
+
import { codec } from '@timber-js/app/codec';
|
|
12
|
+
|
|
13
|
+
export default defineSchema({
|
|
14
|
+
segmentParams: {
|
|
15
|
+
'[id]': codec.string,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Streaming lets the server send HTML to the browser in chunks as it becomes ready. timber uses streaming selectively — the shell is sent as a complete block, and only `<Suspense>` boundaries stream in afterward.
|
|
21
|
+
|
|
22
|
+
## The Shell vs. Suspense Boundaries
|
|
23
|
+
|
|
24
|
+
timber divides your page into two phases:
|
|
25
|
+
|
|
26
|
+
**The shell** (before the [flush point](/docs/the-flush-point)):
|
|
27
|
+
- Layouts, navigation, page structure
|
|
28
|
+
- Primary content that defines the page
|
|
29
|
+
- Determines the HTTP status code
|
|
30
|
+
|
|
31
|
+
**Suspense boundaries** (after the flush):
|
|
32
|
+
- Secondary content wrapped in `<Suspense>`
|
|
33
|
+
- Streams in progressively as data resolves
|
|
34
|
+
- Cannot affect the status code
|
|
35
|
+
|
|
36
|
+
```tsx title="app/products/[id]/page.tsx" use="schema"
|
|
37
|
+
import { Suspense } from 'react';
|
|
38
|
+
import { SEGMENT_PATH } from './$segment';
|
|
39
|
+
import { deny, getSegmentParams } from '@timber-js/app/server';
|
|
40
|
+
|
|
41
|
+
declare function getProduct(id: string): Promise<{ id: string; name: string } | null>;
|
|
42
|
+
declare function ReviewsSkeleton(): React.ReactElement;
|
|
43
|
+
declare function ProductReviews(props: { productId: string }): React.ReactElement;
|
|
44
|
+
|
|
45
|
+
export default async function ProductPage() {
|
|
46
|
+
const { id } = getSegmentParams(SEGMENT_PATH);
|
|
47
|
+
const product = await getProduct(id);
|
|
48
|
+
if (!product) deny(404); // Real HTTP 404
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div>
|
|
52
|
+
<h1>{product.name}</h1>
|
|
53
|
+
<Suspense fallback={<ReviewsSkeleton />}>
|
|
54
|
+
<ProductReviews productId={product.id} />
|
|
55
|
+
</Suspense>
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The product loads before the flush — if it doesn't exist, the server sends a real 404. Reviews stream in later.
|
|
62
|
+
|
|
63
|
+
## Choosing What to Stream
|
|
64
|
+
|
|
65
|
+
**Don't stream** (keep in the shell):
|
|
66
|
+
- Content that defines the page — the product, the article, the user profile
|
|
67
|
+
- Content that might produce a 404 or redirect
|
|
68
|
+
- Content that should be visible without JavaScript
|
|
69
|
+
|
|
70
|
+
**Do stream** (wrap in `<Suspense>`):
|
|
71
|
+
- Recommendations, related items, activity feeds
|
|
72
|
+
- Analytics widgets, personalization
|
|
73
|
+
- Anything slow that isn't essential to the page's identity
|
|
74
|
+
|
|
75
|
+
The rule: if missing content means the page shouldn't exist, don't stream it.
|
|
76
|
+
|
|
77
|
+
## No `loading.tsx`
|
|
78
|
+
|
|
79
|
+
There is no `loading.tsx` convention. timber does not insert Suspense boundaries for you. If you want a loading state, you place `<Suspense>` explicitly. This keeps you in control of what streams and what blocks.
|
|
80
|
+
|
|
81
|
+
## The Layout Suspense Footgun
|
|
82
|
+
|
|
83
|
+
Wrapping `children` in `<Suspense>` inside a layout surrenders HTTP correctness for every page in that subtree:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
// ⚠️ Don't do this
|
|
87
|
+
export default function Layout({ children }: { children: React.ReactNode }) {
|
|
88
|
+
return (
|
|
89
|
+
<Shell>
|
|
90
|
+
<Suspense fallback={<Skeleton />}>{children}</Suspense>
|
|
91
|
+
</Shell>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The framework warns in dev mode when this is detected. For navigation loading states, use `usePendingNavigation()` instead.
|
|
97
|
+
|
|
98
|
+
## `deferSuspenseFor`
|
|
99
|
+
|
|
100
|
+
Sometimes Suspense content resolves fast enough that you'd rather wait for it than show a fallback. `deferSuspenseFor` holds the SSR stream for a specified duration:
|
|
101
|
+
|
|
102
|
+
```tsx title="app/products/[id]/page.tsx" use="schema"
|
|
103
|
+
import { Suspense } from 'react';
|
|
104
|
+
import { SEGMENT_PATH } from './$segment';
|
|
105
|
+
import { deny, getSegmentParams } from '@timber-js/app/server';
|
|
106
|
+
|
|
107
|
+
declare function getProduct(id: string): Promise<{ id: string; name: string } | null>;
|
|
108
|
+
declare function ProductHeader(props: { product: { name: string } }): React.ReactElement;
|
|
109
|
+
declare function ReviewsSkeleton(): React.ReactElement;
|
|
110
|
+
declare function ProductReviews(props: { productId: string }): React.ReactElement;
|
|
111
|
+
|
|
112
|
+
export const deferSuspenseFor = 200; // milliseconds
|
|
113
|
+
|
|
114
|
+
export default async function ProductPage() {
|
|
115
|
+
const { id } = getSegmentParams(SEGMENT_PATH);
|
|
116
|
+
const product = await getProduct(id);
|
|
117
|
+
if (!product) deny(404);
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<div>
|
|
121
|
+
<ProductHeader product={product} />
|
|
122
|
+
<Suspense fallback={<ReviewsSkeleton />}>
|
|
123
|
+
<ProductReviews productId={product.id} />
|
|
124
|
+
</Suspense>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
If reviews resolve within 200ms, they render inline — no fallback shown. If they take longer, the fallback flushes and reviews stream in when ready.
|
|
131
|
+
|
|
132
|
+
## Signal Promotion
|
|
133
|
+
|
|
134
|
+
When `deny()` or `redirect()` fires inside a `<Suspense>` boundary:
|
|
135
|
+
|
|
136
|
+
**Before the flush** — the signal is promoted to pre-flush semantics. The framework sends the correct HTTP status code and renders the appropriate status file.
|
|
137
|
+
|
|
138
|
+
**After the flush** — the status code is already committed. The signal triggers an error boundary in the client, and timber adds `<meta name="robots" content="noindex">`.
|
|
139
|
+
|
|
140
|
+
`deferSuspenseFor` extends the window where signals can be promoted.
|
|
141
|
+
|
|
142
|
+
**The rule:** don't rely on Suspense-wrapped content to control the status code. If content must drive the status code, fetch it outside `<Suspense>`. Signal promotion is a safety net, not a guarantee.
|
|
143
|
+
|
|
144
|
+
## Early Hints (103)
|
|
145
|
+
|
|
146
|
+
Before the flush, timber sends 103 Early Hints with CSS, fonts, and JS URLs. These fire at route-match time — before middleware runs — based on the build manifest. The browser starts fetching resources while the server is still working.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Caching'
|
|
3
|
+
description: 'Explicit caching with timber.cache — TTL, tags, staleWhileRevalidate, and pluggable backends.'
|
|
4
|
+
slug: 'caching'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Caching
|
|
8
|
+
|
|
9
|
+
timber.js does not cache anything by default. No patched `fetch`, no implicit data cache. If you want caching, you ask for it explicitly.
|
|
10
|
+
|
|
11
|
+
## timber.cache vs React.cache
|
|
12
|
+
|
|
13
|
+
This is the number one confusion point. They are different things:
|
|
14
|
+
|
|
15
|
+
| | `timber.cache` | `React.cache` |
|
|
16
|
+
| ------------------- | --------------------------- | -------------------- |
|
|
17
|
+
| Scope | Cross-request (persistent) | Single request |
|
|
18
|
+
| TTL/tags | Yes | No |
|
|
19
|
+
| Works in middleware | Yes | No |
|
|
20
|
+
| Use case | Database queries, API calls | Request-scoped dedup |
|
|
21
|
+
|
|
22
|
+
`React.cache` deduplicates within a single request — if three components call `getUser(id)`, only one database query runs. `timber.cache` persists across requests with TTL — the same query serves cached results for 60 seconds.
|
|
23
|
+
|
|
24
|
+
```tsx title="lib/data.ts"
|
|
25
|
+
import { cache } from 'react';
|
|
26
|
+
import { cache as timberCache } from '@timber-js/app/cache';
|
|
27
|
+
|
|
28
|
+
declare const db: {
|
|
29
|
+
users: { findUnique(opts: { where: { id: string } }): Promise<{ id: string; name: string }> };
|
|
30
|
+
products: { findPopular(): Promise<{ id: string; name: string }[]> };
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Deduplicates within one request
|
|
34
|
+
export const getUser = cache(async (id: string) => {
|
|
35
|
+
return db.users.findUnique({ where: { id } });
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Caches across requests for 60 seconds
|
|
39
|
+
export const getPopularProducts = timberCache(
|
|
40
|
+
async () => {
|
|
41
|
+
return db.products.findPopular();
|
|
42
|
+
},
|
|
43
|
+
{ ttl: 60, tags: ['products'] }
|
|
44
|
+
);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## `timber.cache()` Options
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { cache } from '@timber-js/app/cache';
|
|
51
|
+
|
|
52
|
+
declare const db: {
|
|
53
|
+
users: { findUnique(opts: { where: { id: string } }): Promise<{ id: string; name: string }> };
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const getUser = cache(
|
|
57
|
+
async (userId: string) => {
|
|
58
|
+
return db.users.findUnique({ where: { id: userId } });
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
ttl: 60, // Cache for 60 seconds
|
|
62
|
+
key: (userId) => `user:${userId}`, // Explicit cache key (optional)
|
|
63
|
+
staleWhileRevalidate: true, // Serve stale while refetching
|
|
64
|
+
tags: (userId) => [`user:${userId}`], // For tag-based invalidation
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`tags` accepts a static array (`['products']`) or a function that receives the same arguments as the wrapped function.
|
|
70
|
+
|
|
71
|
+
## Cache Keys
|
|
72
|
+
|
|
73
|
+
Without an explicit `key`, the cache key is derived from the call site plus a deterministic serialization of the arguments.
|
|
74
|
+
|
|
75
|
+
### Content-Derived Cache Identities
|
|
76
|
+
|
|
77
|
+
The call-site identity is content-based — derived from the source code of the `cache()` call, not its position in the file. This means:
|
|
78
|
+
|
|
79
|
+
- **Unchanged code = cache survives deploys.** If you redeploy without changing a cached function, its entries remain valid on persistent handlers like Redis or KV.
|
|
80
|
+
- **Changed code = automatic invalidation.** Editing the wrapped function or its options changes the cache identity, which invalidates old entries without manual cache busting.
|
|
81
|
+
|
|
82
|
+
This works for namespace imports, re-exports, and other patterns where the call site isn't trivially traceable. For callsites that can't be statically traced, a deterministic source-hash runtime fallback ensures cache identities never collide across instances.
|
|
83
|
+
|
|
84
|
+
Object key order doesn't matter — `{ a: 1, b: 2 }` and `{ b: 2, a: 1 }` produce the same key. `Date`, `URL`, and anything with a `toJSON()` method serialize the way `JSON.stringify` would; `Map` and `Set` are serialized by their entries.
|
|
85
|
+
|
|
86
|
+
Arguments that can't be serialized faithfully — functions, symbols, or class instances whose data lives behind getters with no `toJSON()` — throw a `TypeError` instead of silently colliding. If you hit this, pass an explicit `key`:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
cache(fn, { ttl: 60, key: (session) => `events:${session.userId}` });
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Invalidation
|
|
93
|
+
|
|
94
|
+
Invalidate by tag:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { revalidateTag } from '@timber-js/app/server';
|
|
98
|
+
|
|
99
|
+
// In a server action after updating a product:
|
|
100
|
+
revalidateTag('products');
|
|
101
|
+
revalidateTag(`user:${userId}`);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Invalidation wins races against in-flight cached functions: if a cached function is mid-execution when you invalidate one of its tags (the usual mutation flow — update the database, then `revalidateTag`), its result is not written back to the cache, and callers arriving after the invalidation re-execute instead of joining the superseded execution. This guard is per-process; with a shared handler (Redis/KV), an invalidation from a *different* instance can still race a concurrent write on this one.
|
|
105
|
+
|
|
106
|
+
## `staleWhileRevalidate`
|
|
107
|
+
|
|
108
|
+
When enabled, expired entries are served immediately while a background refetch runs:
|
|
109
|
+
|
|
110
|
+
- **0–60s:** Fresh. Served from cache.
|
|
111
|
+
- **60s+:** Stale. Served immediately, background refetch starts.
|
|
112
|
+
- **Next request after refetch:** Gets fresh data.
|
|
113
|
+
|
|
114
|
+
On serverless platforms (Cloudflare Workers, Lambda), the background refetch is automatically registered with the platform's `waitUntil` so it completes even after the response is sent. If the refetch fails, the stale entry continues to be served and the error is logged.
|
|
115
|
+
|
|
116
|
+
## Singleflight
|
|
117
|
+
|
|
118
|
+
When multiple concurrent requests miss the cache for the same key, only one executes the underlying function. The rest wait for the result. The result is written to the cache exactly once, by the execution that ran the function. This is built in — no opt-in needed.
|
|
119
|
+
|
|
120
|
+
## Cache Handlers
|
|
121
|
+
|
|
122
|
+
The default handler is in-memory. Configure a different backend in `timber.config.ts`:
|
|
123
|
+
|
|
124
|
+
```ts title="timber.config.ts"
|
|
125
|
+
import { MemoryCacheHandler } from '@timber-js/app/cache';
|
|
126
|
+
|
|
127
|
+
export default {
|
|
128
|
+
cacheHandler: new MemoryCacheHandler(),
|
|
129
|
+
};
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Implement the `CacheHandler` interface for Redis, Cloudflare KV, or any other backend. See the [Cache API Reference](/docs/api-cache).
|
|
133
|
+
|
|
134
|
+
import SlowStaticComponent from '@/ui/SlowStaticComponent';
|
|
135
|
+
|
|
136
|
+
<SlowStaticComponent />
|