@timber-js/app 0.2.0-alpha.18 → 0.2.0-alpha.181
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-O_LsyCE4.js +317 -0
- package/dist/_chunks/actions-O_LsyCE4.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-B-lhk9p4.js +1202 -0
- package/dist/_chunks/cache-api-B-lhk9p4.js.map +1 -0
- package/dist/_chunks/canonicalize-DQHyFClh.js +248 -0
- package/dist/_chunks/canonicalize-DQHyFClh.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-D3naS3eH.js +688 -0
- package/dist/_chunks/cli-schema-sync-D3naS3eH.js.map +1 -0
- package/dist/_chunks/cloudflare-AHoWYTYr.js +1188 -0
- package/dist/_chunks/cloudflare-AHoWYTYr.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-COtkxMRT.js +191 -0
- package/dist/_chunks/define-COtkxMRT.js.map +1 -0
- package/dist/_chunks/define-c4au4I9R.js +82 -0
- package/dist/_chunks/define-c4au4I9R.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/json-lossy-check-ClNvBM_3.js +63 -0
- package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +1 -0
- package/dist/_chunks/logger-AWfuX-KJ.js +1468 -0
- package/dist/_chunks/logger-AWfuX-KJ.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---kTF5v8.js +315 -0
- package/dist/_chunks/plugin-context---kTF5v8.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-Dz3fcFUo.js +50 -0
- package/dist/_chunks/resolve-schema-Dz3fcFUo.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-DT_Tn0Xf.js +119 -0
- package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +1 -0
- package/dist/_chunks/segment-classify-Byy425ng.js +176 -0
- package/dist/_chunks/segment-classify-Byy425ng.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/{use-query-states-D5KaffOK.js → use-query-states-DFvWd-EA.js} +71 -26
- package/dist/_chunks/use-query-states-DFvWd-EA.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-BtTlKviE.js +1002 -0
- package/dist/_chunks/walkers-BtTlKviE.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 +65 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +124 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +189 -21
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +2 -188
- 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 +41 -3
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +224 -172
- 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 +2 -6
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/cache/cache-api.d.ts +48 -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 +31 -8
- 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/json-lossy-check.d.ts +11 -0
- package/dist/cache/json-lossy-check.d.ts.map +1 -0
- package/dist/cache/redis-handler.d.ts +140 -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 +52 -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 +35 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +113 -34
- 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 +27 -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/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 +21 -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 +185 -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 +938 -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 +121 -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 +99 -14
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +62 -15
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +30 -7
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +57 -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/slot-context.d.ts +31 -0
- package/dist/client/slot-context.d.ts.map +1 -0
- package/dist/client/slot-outlet.d.ts +16 -0
- package/dist/client/slot-outlet.d.ts.map +1 -0
- package/dist/client/slot-provider.d.ts +25 -0
- package/dist/client/slot-provider.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 +76 -0
- package/dist/codec.js.map +1 -0
- package/dist/config-types.d.ts +284 -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} +17 -3
- 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 +177 -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 +9243 -14093
- 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 +217 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +21 -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 +28 -4
- 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-options-analysis.d.ts +40 -0
- package/dist/plugins/prebuilt-options-analysis.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/request-dep.d.ts +21 -0
- package/dist/plugins/request-dep.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 +81 -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 +81 -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 +188 -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 +34 -441
- 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 +42 -7
- 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 +93 -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 +12 -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 +117 -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 +242 -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 +182 -2906
- 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 +3892 -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 +60 -11
- package/dist/server/metadata-routes.d.ts.map +1 -1
- package/dist/server/metadata.d.ts +8 -0
- package/dist/server/metadata.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +19 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +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 +59 -0
- package/dist/server/pipeline-phases.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +140 -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 +62 -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/key-discipline.d.ts +23 -0
- package/dist/server/prebuilt/key-discipline.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/slots.d.ts +99 -0
- package/dist/server/prebuilt/slots.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 +111 -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/request-dep.d.ts +15 -0
- package/dist/server/request-dep.d.ts.map +1 -0
- package/dist/server/route-element-builder.d.ts +53 -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/deny-fallback.d.ts +29 -0
- package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -0
- 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 +69 -37
- 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 +51 -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 +6 -6
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +25 -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 +36 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +89 -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 +66 -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 +72 -9
- 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 +69 -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 +120 -120
- package/dist/shims/image.d.ts.map +1 -1
- 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 +311 -0
- package/docs/api/33-api-search-params.mdx +154 -0
- package/docs/api/34-api-config.mdx +325 -0
- package/docs/api/35-api-typescript.mdx +170 -0
- package/docs/api/36-cli.mdx +143 -0
- package/docs/learn/00-introduction.mdx +109 -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 +252 -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 +176 -0
- package/docs/learn/13-configuration.mdx +162 -0
- package/docs/learn/14-deploying.mdx +264 -0
- package/docs/more/01-advanced-routing.mdx +173 -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 +105 -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 +204 -0
- package/src/adapters/cloudflare.ts +620 -129
- package/src/adapters/compress-module.ts +27 -92
- package/src/adapters/nitro.ts +266 -122
- package/src/adapters/raw-imports.d.ts +5 -0
- package/src/adapters/shared.ts +68 -0
- package/src/adapters/types.ts +2 -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 +114 -21
- package/src/cache/invalidation-epoch.ts +93 -0
- package/src/cache/json-lossy-check.ts +75 -0
- package/src/cache/redis-handler.ts +197 -19
- 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 +237 -0
- package/src/cache/timber-cache.ts +161 -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 +401 -0
- package/src/cli.ts +167 -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 +113 -0
- package/src/client/browser-entry/post-hydration.ts +110 -0
- package/src/client/browser-entry/router-init.ts +286 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +50 -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 +21 -6
- package/src/client/index.ts +67 -45
- package/src/client/internal.ts +58 -0
- package/src/client/link.tsx +349 -150
- package/src/client/navigation-api.ts +345 -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 +589 -215
- package/src/client/rsc-fetch.ts +251 -34
- package/src/client/segment-cache.ts +105 -17
- package/src/client/segment-outlet.tsx +141 -0
- package/src/client/segment-update-context.ts +42 -0
- package/src/client/shallow-url.ts +22 -0
- package/src/client/slot-context.ts +50 -0
- package/src/client/slot-outlet.tsx +22 -0
- package/src/client/slot-provider.tsx +32 -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 +108 -10
- 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 +149 -0
- package/src/config-types.ts +282 -0
- package/src/config-validation.ts +330 -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} +122 -26
- 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 +100 -18
- package/src/fonts/local.ts +9 -8
- package/src/fonts/paths.ts +58 -0
- package/src/fonts/pipeline.ts +348 -0
- package/src/fonts/transform.ts +311 -0
- package/src/fonts/types.ts +52 -1
- package/src/fonts/virtual-modules.ts +179 -0
- package/src/index.ts +446 -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 +432 -0
- package/src/plugins/adapter-build.ts +220 -7
- package/src/plugins/build-manifest.ts +177 -23
- package/src/plugins/build-report.ts +253 -35
- package/src/plugins/cache.ts +243 -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 +185 -0
- package/src/plugins/cloudflare-wasm.ts +141 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-server.ts +284 -94
- package/src/plugins/entries.ts +134 -16
- package/src/plugins/fonts.ts +225 -660
- package/src/plugins/mdx.ts +47 -10
- package/src/plugins/prebuilt-capture.ts +217 -0
- package/src/plugins/prebuilt-options-analysis.ts +175 -0
- package/src/plugins/prebuilt.ts +655 -0
- package/src/plugins/prerender-sugar.ts +328 -0
- package/src/plugins/request-dep.ts +458 -0
- package/src/plugins/routing.ts +237 -241
- package/src/plugins/server-bundle.ts +89 -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 +372 -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 +313 -0
- package/src/routing/manifest-codegen.ts +287 -0
- package/src/routing/scanner.ts +338 -189
- package/src/routing/schema-validation.ts +155 -0
- package/src/routing/segment-classify.ts +223 -0
- package/src/routing/segment-codegen.ts +98 -0
- package/src/routing/types.ts +82 -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 +253 -0
- package/src/search-params/define.ts +576 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +101 -0
- package/src/segment-params/define.ts +249 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +111 -34
- package/src/server/action-client.ts +120 -29
- 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 +137 -20
- package/src/server/asset-headers.ts +15 -37
- package/src/server/body-limits.ts +10 -2
- package/src/server/build-manifest.ts +19 -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 +314 -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 +495 -0
- package/src/server/html-injectors.ts +271 -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 +205 -24
- package/src/server/metadata.ts +21 -0
- package/src/server/middleware-runner.ts +31 -4
- package/src/server/node-stream-transforms.ts +336 -0
- package/src/server/param-coercion.ts +207 -0
- package/src/server/pipeline-helpers.ts +204 -0
- package/src/server/pipeline-interception.ts +45 -18
- package/src/server/pipeline-metadata.ts +14 -0
- package/src/server/pipeline-outcome.ts +197 -0
- package/src/server/pipeline-phases.ts +545 -0
- package/src/server/pipeline.ts +274 -382
- package/src/server/port-resolution.ts +215 -0
- package/src/server/prebuilt/cache-key.ts +298 -0
- package/src/server/prebuilt/capture-state.ts +89 -0
- package/src/server/prebuilt/key-discipline.ts +53 -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/slots.ts +190 -0
- package/src/server/prebuilt/synthetic-store.ts +121 -0
- package/src/server/prebuilt-builder.ts +809 -0
- package/src/server/prebuilt-runtime.ts +815 -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 +170 -337
- package/src/server/request-dep.ts +37 -0
- package/src/server/route-element-builder.ts +699 -295
- package/src/server/route-handler.ts +31 -4
- package/src/server/route-matcher.ts +158 -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/deny-fallback.ts +92 -0
- package/src/server/rsc-entry/error-renderer.ts +306 -89
- package/src/server/rsc-entry/helpers.ts +210 -85
- package/src/server/rsc-entry/index.ts +332 -332
- package/src/server/rsc-entry/render-route.ts +300 -0
- package/src/server/rsc-entry/revalidate-renderer.ts +349 -0
- package/src/server/rsc-entry/rsc-payload.ts +102 -42
- package/src/server/rsc-entry/rsc-stream.ts +93 -13
- package/src/server/rsc-entry/ssr-bridge.ts +18 -5
- package/src/server/rsc-entry/ssr-renderer.ts +275 -43
- package/src/server/rsc-entry/wrap-action-dispatch.ts +186 -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 +345 -0
- package/src/server/sitemap-handler.ts +157 -0
- package/src/server/slot-resolver.ts +574 -250
- package/src/server/ssr-bridge-types.ts +124 -0
- package/src/server/ssr-entry.ts +206 -86
- package/src/server/ssr-render.ts +345 -86
- package/src/server/ssr-wrappers.tsx +141 -0
- package/src/server/state-tree-diff.ts +177 -30
- package/src/server/status-code-resolver.ts +115 -130
- package/src/server/stream-utils.ts +288 -0
- package/src/server/tracing.ts +126 -14
- package/src/server/tree-builder.ts +214 -90
- package/src/server/tree-match.ts +262 -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 +0 -153
- 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/adapters/cloudflare.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,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared href/URL validation for all navigation sinks.
|
|
3
|
+
*
|
|
4
|
+
* Used by <Link>, useRouter().push/replace, and redirectExternal().
|
|
5
|
+
* Single source of truth for dangerous-scheme detection — prevents
|
|
6
|
+
* control-character smuggling that bypasses naive regex checks.
|
|
7
|
+
*
|
|
8
|
+
* See design/13-security.md §"Link scheme injection" (test #9)
|
|
9
|
+
* and design/07-routing.md §"<Link> Scheme Validation".
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* All C0 control characters (U+0000–U+001F) that browsers strip during
|
|
14
|
+
* URL preprocessing. Browsers and `new URL()` strip the full C0 range,
|
|
15
|
+
* not just tab/LF/CR — so we must match that behavior to prevent
|
|
16
|
+
* bypass vectors like `\x00javascript:alert(1)`.
|
|
17
|
+
*/
|
|
18
|
+
// eslint-disable-next-line no-control-regex -- intentional: must match all C0 controls to prevent bypass
|
|
19
|
+
const CONTROL_CHARS_RE = /[\x00-\x1f]/g;
|
|
20
|
+
|
|
21
|
+
const DANGEROUS_SCHEMES = new Set(['javascript:', 'data:', 'vbscript:']);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Strip C0 control chars and leading whitespace, then extract the scheme.
|
|
25
|
+
* Returns the lowercase scheme (e.g. "javascript:") or null if no scheme.
|
|
26
|
+
*/
|
|
27
|
+
function extractScheme(href: string): string | null {
|
|
28
|
+
const cleaned = href.replace(CONTROL_CHARS_RE, '').trimStart();
|
|
29
|
+
const match = /^([a-z][a-z0-9+.-]*:)/i.exec(cleaned);
|
|
30
|
+
return match ? match[1].toLowerCase() : null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Validate an href for navigation sinks (<Link>, useRouter, etc.).
|
|
35
|
+
*
|
|
36
|
+
* Rejects dangerous schemes (javascript:, data:, vbscript:) even when
|
|
37
|
+
* control characters are embedded to bypass naive regex checks.
|
|
38
|
+
* Also rejects protocol-relative URLs (//evil.com).
|
|
39
|
+
*
|
|
40
|
+
* Throws on rejection. Safe hrefs pass through silently.
|
|
41
|
+
*/
|
|
42
|
+
export function validateNavigationHref(href: string): void {
|
|
43
|
+
// Normalize for validation: strip C0 controls, trim, then replace backslashes
|
|
44
|
+
// with forward slashes. Browsers normalize \ → / during URL resolution, so
|
|
45
|
+
// "/\evil.com" becomes "//evil.com" (protocol-relative open redirect).
|
|
46
|
+
const cleaned = href.replace(CONTROL_CHARS_RE, '').trimStart().replaceAll('\\', '/');
|
|
47
|
+
|
|
48
|
+
// Protocol-relative URLs can redirect to attacker-controlled origins
|
|
49
|
+
if (cleaned.startsWith('//')) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
`Navigation received a protocol-relative or backslash-prefixed URL: "${href}". ` +
|
|
52
|
+
'Use an absolute URL with an explicit scheme or a relative path.'
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const scheme = extractScheme(href);
|
|
57
|
+
if (scheme && DANGEROUS_SCHEMES.has(scheme)) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
`Navigation received a dangerous href: "${href}". ` +
|
|
60
|
+
'javascript:, data:, and vbscript: URLs are not allowed.'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Check if an href is internal (same-origin navigation) or external.
|
|
67
|
+
*
|
|
68
|
+
* Strips control characters before checking so that "java\tscript:" is
|
|
69
|
+
* correctly identified as having a scheme (and thus not internal).
|
|
70
|
+
*/
|
|
71
|
+
export function isInternalHref(href: string): boolean {
|
|
72
|
+
const cleaned = href.replace(CONTROL_CHARS_RE, '').trimStart().replaceAll('\\', '/');
|
|
73
|
+
|
|
74
|
+
if (cleaned.startsWith('//')) return false;
|
|
75
|
+
if (cleaned.startsWith('/') || cleaned.startsWith('#') || cleaned.startsWith('?')) return true;
|
|
76
|
+
|
|
77
|
+
const scheme = extractScheme(href);
|
|
78
|
+
if (scheme) return false;
|
|
79
|
+
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Pattern matching absolute URLs: any scheme (http:, javascript:, …) or protocol-relative // */
|
|
84
|
+
const ABSOLUTE_URL_RE = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/)/;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Assert that a redirect target is a relative path — rejects absolute and
|
|
88
|
+
* protocol-relative URLs. Used by both the server `redirect()` primitive and
|
|
89
|
+
* the client next/navigation shim so they enforce identical semantics.
|
|
90
|
+
*
|
|
91
|
+
* Normalizes for validation only: strips C0 controls, trims, then replaces
|
|
92
|
+
* backslashes with forward slashes. Browsers normalize \ → / during URL
|
|
93
|
+
* resolution, so "/\evil.com" becomes "//evil.com" (protocol-relative open
|
|
94
|
+
* redirect). See design/13-security.md tests #8, #8a–#8c.
|
|
95
|
+
*/
|
|
96
|
+
export function assertRelativeRedirectPath(path: string): void {
|
|
97
|
+
const cleaned = path.replace(CONTROL_CHARS_RE, '').trimStart().replaceAll('\\', '/');
|
|
98
|
+
|
|
99
|
+
if (ABSOLUTE_URL_RE.test(cleaned)) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`redirect() only accepts relative URLs. Got absolute URL: "${path}". ` +
|
|
102
|
+
'Use redirectExternal(url, allowList) for external redirects.'
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// eslint-disable-next-line no-control-regex -- intentional: must match C0 controls
|
|
107
|
+
if (/[\x00-\x1f]/.test(path)) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`redirect() received a path containing control characters (U+0000–U+001F). ` +
|
|
110
|
+
'Sanitize user input before passing it to redirect().'
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const SAFE_REDIRECT_SCHEMES = new Set(['http:', 'https:']);
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Validate and canonicalize an external redirect URL.
|
|
119
|
+
*
|
|
120
|
+
* Requires http: or https: scheme and checks origin against an allow-list.
|
|
121
|
+
* Returns the parsed canonical URL string (from URL.href) to prevent
|
|
122
|
+
* raw user input from reaching the Location header.
|
|
123
|
+
*
|
|
124
|
+
* @throws On invalid URL, dangerous scheme, or origin not in allow-list.
|
|
125
|
+
*/
|
|
126
|
+
export function validateExternalRedirectUrl(url: string, allowList: string[]): string {
|
|
127
|
+
// Strip control chars before parsing to prevent scheme smuggling
|
|
128
|
+
const cleaned = url.replace(CONTROL_CHARS_RE, '').trimStart();
|
|
129
|
+
|
|
130
|
+
if (cleaned.startsWith('//')) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`redirectExternal() received a protocol-relative URL: "${url}". ` +
|
|
133
|
+
'Use an absolute URL with http: or https: scheme.'
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let parsed: URL;
|
|
138
|
+
try {
|
|
139
|
+
parsed = new URL(cleaned);
|
|
140
|
+
} catch {
|
|
141
|
+
throw new Error(`redirectExternal() received an invalid URL: "${url}"`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (!SAFE_REDIRECT_SCHEMES.has(parsed.protocol)) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`redirectExternal() received a non-http(s) URL: "${url}". ` +
|
|
147
|
+
'Only http: and https: schemes are allowed for external redirects.'
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!allowList.includes(parsed.origin)) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`redirectExternal() target "${parsed.origin}" is not in the allow-list. ` +
|
|
154
|
+
`Allowed: [${allowList.join(', ')}]`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return parsed.href;
|
|
159
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility for merging preserved search params into a target URL.
|
|
3
|
+
*
|
|
4
|
+
* Used by both <Link> (client) and redirect() (server). Extracted to a shared
|
|
5
|
+
* module to avoid importing client code ('use client') from server modules.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Merge preserved search params from the current URL into a target href.
|
|
10
|
+
*
|
|
11
|
+
* When `preserve` is `true`, all current search params are merged.
|
|
12
|
+
* When `preserve` is a `string[]`, only the named params are merged.
|
|
13
|
+
*
|
|
14
|
+
* The target href's own search params take precedence — preserved params
|
|
15
|
+
* are only added if the target doesn't already define them.
|
|
16
|
+
*
|
|
17
|
+
* @param targetHref - The resolved target href (may already contain query string)
|
|
18
|
+
* @param currentSearch - The current URL's search string (e.g. "?private=access&page=2")
|
|
19
|
+
* @param preserve - `true` to preserve all, or `string[]` to preserve specific params
|
|
20
|
+
* @returns The target href with preserved search params merged in
|
|
21
|
+
*/
|
|
22
|
+
export function mergePreservedSearchParams(
|
|
23
|
+
targetHref: string,
|
|
24
|
+
currentSearch: string,
|
|
25
|
+
preserve: true | string[]
|
|
26
|
+
): string {
|
|
27
|
+
const currentParams = new URLSearchParams(currentSearch);
|
|
28
|
+
if (currentParams.size === 0) return targetHref;
|
|
29
|
+
|
|
30
|
+
// Split hash fragment from target before processing query params.
|
|
31
|
+
// Hash must come after query string: /path?query=value#hash
|
|
32
|
+
const hashIdx = targetHref.indexOf('#');
|
|
33
|
+
const hrefWithoutHash = hashIdx >= 0 ? targetHref.slice(0, hashIdx) : targetHref;
|
|
34
|
+
const hash = hashIdx >= 0 ? targetHref.slice(hashIdx) : '';
|
|
35
|
+
|
|
36
|
+
// Split target into path and existing query
|
|
37
|
+
const qIdx = hrefWithoutHash.indexOf('?');
|
|
38
|
+
const targetPath = qIdx >= 0 ? hrefWithoutHash.slice(0, qIdx) : hrefWithoutHash;
|
|
39
|
+
const targetParams = new URLSearchParams(qIdx >= 0 ? hrefWithoutHash.slice(qIdx + 1) : '');
|
|
40
|
+
|
|
41
|
+
// Collect params to preserve (that aren't already in the target)
|
|
42
|
+
const merged = new URLSearchParams(targetParams);
|
|
43
|
+
for (const [key, value] of currentParams) {
|
|
44
|
+
// Only preserve if: (a) not already in target, and (b) included in preserve list
|
|
45
|
+
if (!targetParams.has(key)) {
|
|
46
|
+
if (preserve === true || preserve.includes(key)) {
|
|
47
|
+
merged.append(key, value);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const qs = merged.toString();
|
|
53
|
+
const pathWithQuery = qs ? `${targetPath}?${qs}` : targetPath;
|
|
54
|
+
return pathWithQuery + hash;
|
|
55
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js redirect type discriminator.
|
|
3
|
+
*
|
|
4
|
+
* Provided for API compatibility with libraries that import `RedirectType`
|
|
5
|
+
* from `next/navigation`. In timber, `redirect()` always uses `replace`
|
|
6
|
+
* semantics (no history entry for the redirect itself).
|
|
7
|
+
*
|
|
8
|
+
* Lives in shared/ (isomorphic) so both the server primitives and the
|
|
9
|
+
* client-only next/navigation shim export the same definition without the
|
|
10
|
+
* client shim pulling in server code.
|
|
11
|
+
*/
|
|
12
|
+
export const RedirectType = {
|
|
13
|
+
push: 'push',
|
|
14
|
+
replace: 'replace',
|
|
15
|
+
} as const;
|
|
16
|
+
|
|
17
|
+
export type RedirectTypeValue = (typeof RedirectType)[keyof typeof RedirectType];
|
package/src/shims/font-google.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* Design doc: 24-fonts.md, "Next.js Font Compatibility"
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import type { GoogleFontConfig, FontResult } from '
|
|
20
|
+
import type { GoogleFontConfig, FontResult } from '../fonts/types.js';
|
|
21
21
|
|
|
22
22
|
export type { GoogleFontConfig, FontResult };
|
|
23
23
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback shim for `next/font/local` → `@timber/fonts/local`.
|
|
3
|
+
*
|
|
4
|
+
* At build time, the timber-fonts plugin's transform hook replaces
|
|
5
|
+
* `localFont()` calls with static FontResult objects containing real
|
|
6
|
+
* class names and font stacks. This file serves two purposes:
|
|
7
|
+
*
|
|
8
|
+
* 1. **TypeScript resolution** — provides types for IDEs and `tsc` outside
|
|
9
|
+
* of Vite's module graph (where the virtual module handles it).
|
|
10
|
+
* 2. **Runtime fallback** — returns empty className/fontFamily values when
|
|
11
|
+
* the plugin hasn't processed a call (e.g. in tests or non-Vite environments).
|
|
12
|
+
*
|
|
13
|
+
* Design doc: 24-fonts.md, "Next.js Font Compatibility"
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { LocalFontConfig, FontResult } from '../fonts/types.js';
|
|
17
|
+
|
|
18
|
+
export type { LocalFontConfig, FontResult };
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a local font.
|
|
22
|
+
*
|
|
23
|
+
* The timber-fonts plugin replaces these calls at build time with real
|
|
24
|
+
* class names and font stacks. This stub ensures code that imports
|
|
25
|
+
* `localFont` outside of the build pipeline (tests, type-checking)
|
|
26
|
+
* gets a valid FontResult shape without runtime errors.
|
|
27
|
+
*/
|
|
28
|
+
export default function localFont(config?: LocalFontConfig): FontResult {
|
|
29
|
+
return {
|
|
30
|
+
className: '',
|
|
31
|
+
style: { fontFamily: '' },
|
|
32
|
+
variable: config?.variable,
|
|
33
|
+
};
|
|
34
|
+
}
|
package/src/shims/headers.ts
CHANGED
|
@@ -4,6 +4,127 @@
|
|
|
4
4
|
* Imports from @timber-js/app/server which Vite resolves to dist/server/index.js
|
|
5
5
|
* via native package.json exports. This ensures the same ALS singleton as the
|
|
6
6
|
* pipeline (both import from the same shared request-context chunk in dist/).
|
|
7
|
+
*
|
|
8
|
+
* `cookies()` is NOT a bare alias of `getCookieJar()`: Next.js's
|
|
9
|
+
* RequestCookies returns `{ name, value }` RequestCookie objects from
|
|
10
|
+
* `.get()`/`.getAll()`, while timber's native jar returns bare strings from
|
|
11
|
+
* `.get()`. Ecosystem libraries written against the real API use
|
|
12
|
+
* `(await cookies()).get('session')?.value` — with the bare-string shape
|
|
13
|
+
* that silently reads `undefined` off a string. The adapter below presents
|
|
14
|
+
* the Next shape while delegating every operation to the timber jar, so the
|
|
15
|
+
* encoding contract, cookie-octet validation, and mutable-context checks
|
|
16
|
+
* (design/29-cookies.md, ONGOING_SECURITY.md H-3) apply unchanged.
|
|
17
|
+
* See TIM-1042 and design/14-ecosystem.md §next/headers.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { getCookieJar } from '@timber-js/app/server';
|
|
21
|
+
import type { CookieOptions, SetCookieOptions } from '@timber-js/app/server';
|
|
22
|
+
|
|
23
|
+
// Re-export timber's primary API
|
|
24
|
+
export { getHeaders, getCookieJar } from '@timber-js/app/server';
|
|
25
|
+
|
|
26
|
+
// Next.js compat alias — libraries importing from 'next/headers' expect this name.
|
|
27
|
+
export { getHeaders as headers } from '@timber-js/app/server';
|
|
28
|
+
|
|
29
|
+
/** Next.js's request cookie shape: `cookies().get(name)` → `{ name, value }`. */
|
|
30
|
+
export interface RequestCookie {
|
|
31
|
+
name: string;
|
|
32
|
+
value: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Next.js's `cookies().set()` options — `expires` may be a ms timestamp. */
|
|
36
|
+
export interface NextCookieOptions extends Omit<SetCookieOptions, 'expires'> {
|
|
37
|
+
expires?: Date | number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Next.js's object overload for `cookies().set({ name, value, ...options })`. */
|
|
41
|
+
export interface NextCookieListItem extends NextCookieOptions {
|
|
42
|
+
name: string;
|
|
43
|
+
value: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Next.js's RequestCookies surface, backed by timber's cookie jar. */
|
|
47
|
+
export interface NextRequestCookies {
|
|
48
|
+
get(name: string): RequestCookie | undefined;
|
|
49
|
+
get(cookie: RequestCookie): RequestCookie | undefined;
|
|
50
|
+
getAll(name?: string): RequestCookie[];
|
|
51
|
+
getAll(cookie: RequestCookie): RequestCookie[];
|
|
52
|
+
has(name: string): boolean;
|
|
53
|
+
readonly size: number;
|
|
54
|
+
set(name: string, value: string, options?: NextCookieOptions): void;
|
|
55
|
+
set(cookie: NextCookieListItem): void;
|
|
56
|
+
delete(name: string): void;
|
|
57
|
+
delete(cookie: { name: string } & Pick<CookieOptions, 'path' | 'domain'>): void;
|
|
58
|
+
[Symbol.iterator](): IterableIterator<[string, RequestCookie]>;
|
|
59
|
+
toString(): string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Normalize Next's `expires?: Date | number` (ms timestamp) to timber's `Date`. */
|
|
63
|
+
function normalizeOptions(options?: NextCookieOptions): SetCookieOptions | undefined {
|
|
64
|
+
if (!options) return undefined;
|
|
65
|
+
const { expires, ...rest } = options;
|
|
66
|
+
if (typeof expires === 'number') return { ...rest, expires: new Date(expires) };
|
|
67
|
+
return options as SetCookieOptions;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Next.js compat: `cookies()` returning the RequestCookies shape.
|
|
72
|
+
*
|
|
73
|
+
* Next.js 15 makes `cookies()` async; awaiting this sync return value works
|
|
74
|
+
* for both the `(await cookies()).get()` and legacy `cookies().get()` call
|
|
75
|
+
* styles, so libraries targeting either Next version resolve correctly.
|
|
7
76
|
*/
|
|
77
|
+
export function cookies(): NextRequestCookies {
|
|
78
|
+
const jar = getCookieJar();
|
|
79
|
+
|
|
80
|
+
const toCookie = (name: string): RequestCookie | undefined => {
|
|
81
|
+
const value = jar.get(name);
|
|
82
|
+
return value === undefined ? undefined : { name, value };
|
|
83
|
+
};
|
|
8
84
|
|
|
9
|
-
|
|
85
|
+
return {
|
|
86
|
+
get(nameOrCookie: string | RequestCookie): RequestCookie | undefined {
|
|
87
|
+
return toCookie(typeof nameOrCookie === 'string' ? nameOrCookie : nameOrCookie.name);
|
|
88
|
+
},
|
|
89
|
+
getAll(nameOrCookie?: string | RequestCookie): RequestCookie[] {
|
|
90
|
+
const all = jar.getAll();
|
|
91
|
+
if (nameOrCookie === undefined) return all;
|
|
92
|
+
const name = typeof nameOrCookie === 'string' ? nameOrCookie : nameOrCookie.name;
|
|
93
|
+
return all.filter((cookie) => cookie.name === name);
|
|
94
|
+
},
|
|
95
|
+
has(name: string): boolean {
|
|
96
|
+
return jar.has(name);
|
|
97
|
+
},
|
|
98
|
+
get size(): number {
|
|
99
|
+
return jar.size;
|
|
100
|
+
},
|
|
101
|
+
set(
|
|
102
|
+
nameOrCookie: string | NextCookieListItem,
|
|
103
|
+
value?: string,
|
|
104
|
+
options?: NextCookieOptions
|
|
105
|
+
): void {
|
|
106
|
+
if (typeof nameOrCookie === 'string') {
|
|
107
|
+
jar.set(nameOrCookie, value as string, normalizeOptions(options));
|
|
108
|
+
} else {
|
|
109
|
+
const { name, value: cookieValue, ...objectOptions } = nameOrCookie;
|
|
110
|
+
jar.set(name, cookieValue, normalizeOptions(objectOptions));
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
delete(nameOrCookie: string | ({ name: string } & Pick<CookieOptions, 'path' | 'domain'>)) {
|
|
114
|
+
if (typeof nameOrCookie === 'string') {
|
|
115
|
+
jar.delete(nameOrCookie);
|
|
116
|
+
} else {
|
|
117
|
+
const { name, ...options } = nameOrCookie;
|
|
118
|
+
jar.delete(name, options);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
*[Symbol.iterator](): IterableIterator<[string, RequestCookie]> {
|
|
122
|
+
for (const cookie of jar.getAll()) {
|
|
123
|
+
yield [cookie.name, cookie];
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
toString(): string {
|
|
127
|
+
return jar.toString();
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shim: next/navigation (client environment only)
|
|
3
3
|
*
|
|
4
|
-
* Re-exports
|
|
5
|
-
*
|
|
6
|
-
* server/primitives.ts
|
|
4
|
+
* Re-exports the client-side hooks from timber's client API, and implements
|
|
5
|
+
* client-render `redirect()` / `permanentRedirect()` / `notFound()` without
|
|
6
|
+
* pulling server/primitives.ts into the browser bundle.
|
|
7
|
+
*
|
|
8
|
+
* Next.js supports calling redirect()/notFound() during client component
|
|
9
|
+
* render. timber matches that by throwing a plain Error carrying the same
|
|
10
|
+
* JSON digest the server pipeline attaches to RedirectSignal/DenySignal.
|
|
11
|
+
* TimberErrorBoundary recognizes the digest and converts it to an SPA
|
|
12
|
+
* navigation (redirect) or a status-code fallback (notFound), and
|
|
13
|
+
* browser-dev's isFrameworkSignalError() keeps it out of the dev overlay.
|
|
7
14
|
*
|
|
8
15
|
* The full shim (navigation.ts) is still used in the RSC and SSR environments
|
|
9
|
-
* where
|
|
16
|
+
* where the real server primitives produce proper HTTP responses.
|
|
10
17
|
*
|
|
11
18
|
* Imports use @timber-js/app/client (not #/ subpath imports) so they resolve
|
|
12
19
|
* to the same module instances as user code in Vite dev — preventing module
|
|
@@ -16,42 +23,57 @@
|
|
|
16
23
|
* See design/14-ecosystem.md §"next/navigation" for the full shim audit.
|
|
17
24
|
*/
|
|
18
25
|
|
|
19
|
-
|
|
26
|
+
import { assertRelativeRedirectPath } from '../shared/href-validation.js';
|
|
27
|
+
import type { RedirectTypeValue } from '../shared/redirect-type.js';
|
|
28
|
+
|
|
29
|
+
// Hooks — useSegmentParams and useSearchParams import from direct modules
|
|
30
|
+
// since they're no longer in @timber-js/app/client public exports.
|
|
31
|
+
export { useSegmentParams, useSegmentParams as useParams } from '../client/use-segment-params.js';
|
|
32
|
+
export { useSearchParams } from '../client/use-search-params.js';
|
|
20
33
|
export {
|
|
21
|
-
useParams,
|
|
22
34
|
usePathname,
|
|
23
|
-
useSearchParams,
|
|
24
35
|
useRouter,
|
|
25
36
|
useSelectedLayoutSegment,
|
|
26
37
|
useSelectedLayoutSegments,
|
|
27
38
|
} from '@timber-js/app/client';
|
|
28
39
|
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
export const RedirectType = {
|
|
32
|
-
push: 'push',
|
|
33
|
-
replace: 'replace',
|
|
34
|
-
} as const;
|
|
40
|
+
// Single source of truth shared with server/primitives.ts.
|
|
41
|
+
export { RedirectType } from '../shared/redirect-type.js';
|
|
35
42
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
throw
|
|
41
|
-
'redirect() is a server-only function and cannot be called from client components. ' +
|
|
42
|
-
'Use useRouter().push() or useRouter().replace() for client-side navigation.'
|
|
43
|
-
);
|
|
43
|
+
/** Throw a plain Error carrying a framework signal digest. */
|
|
44
|
+
function throwSignal(message: string, digest: Record<string, unknown>): never {
|
|
45
|
+
const err = new Error(message);
|
|
46
|
+
(err as Error & { digest?: string }).digest = JSON.stringify(digest);
|
|
47
|
+
throw err;
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Client-render redirect. Throws a redirect-digest error that the nearest
|
|
52
|
+
* TimberErrorBoundary converts into an SPA navigation (replace semantics).
|
|
53
|
+
*
|
|
54
|
+
* The optional RedirectType argument is accepted for Next.js API
|
|
55
|
+
* compatibility but ignored — timber always uses replace semantics,
|
|
56
|
+
* matching the server-side redirect().
|
|
57
|
+
*/
|
|
58
|
+
export function redirect(path: string, _type?: RedirectTypeValue): never {
|
|
59
|
+
assertRelativeRedirectPath(path);
|
|
60
|
+
throwSignal(`Redirect to ${path}`, { type: 'redirect', location: path, status: 302 });
|
|
51
61
|
}
|
|
52
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Client-render permanent redirect. On the client there is no HTTP status —
|
|
65
|
+
* this behaves identically to redirect() apart from the digest's status.
|
|
66
|
+
*/
|
|
67
|
+
export function permanentRedirect(path: string, _type?: RedirectTypeValue): never {
|
|
68
|
+
assertRelativeRedirectPath(path);
|
|
69
|
+
throwSignal(`Redirect to ${path}`, { type: 'redirect', location: path, status: 308 });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Client-render notFound. Throws a deny-digest error (status 404) that the
|
|
74
|
+
* nearest matching TimberErrorBoundary renders as the 404 fallback. The
|
|
75
|
+
* message matches DenySignal's so digest-less fallback parsing still works.
|
|
76
|
+
*/
|
|
53
77
|
export function notFound(): never {
|
|
54
|
-
|
|
55
|
-
'notFound() is a server-only function and cannot be called from client components.'
|
|
56
|
-
);
|
|
78
|
+
throwSignal('Access denied with status 404', { type: 'deny', status: 404, data: null });
|
|
57
79
|
}
|
package/src/shims/navigation.ts
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shim: next/navigation → timber navigation primitives
|
|
3
3
|
*
|
|
4
|
-
* Client hooks import from
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Client hooks import from their direct modules since useSegmentParams,
|
|
5
|
+
* useSearchParams, and useQueryStates are no longer part of
|
|
6
|
+
* @timber-js/app/client public exports (they live on define* factories).
|
|
7
|
+
* The shim re-exports them for next/navigation library compat (nuqs etc).
|
|
8
|
+
*
|
|
9
|
+
* Server functions import from @timber-js/app/server for ALS singleton consistency.
|
|
7
10
|
*/
|
|
8
11
|
|
|
9
|
-
// Hooks
|
|
12
|
+
// Hooks re-exported for next/navigation compat
|
|
13
|
+
export { useSegmentParams, useSegmentParams as useParams } from '../client/use-segment-params.js';
|
|
14
|
+
export { useSearchParams } from '../client/use-search-params.js';
|
|
10
15
|
export {
|
|
11
|
-
useParams,
|
|
12
16
|
usePathname,
|
|
13
|
-
useSearchParams,
|
|
14
17
|
useRouter,
|
|
15
18
|
useSelectedLayoutSegment,
|
|
16
19
|
useSelectedLayoutSegments,
|
|
17
20
|
} from '@timber-js/app/client';
|
|
18
21
|
|
|
19
22
|
// Functions (server-side)
|
|
20
|
-
export { redirect,
|
|
23
|
+
export { redirect, redirectExternal, RedirectType } from '@timber-js/app/server';
|
|
24
|
+
|
|
25
|
+
// Next.js compat aliases — these are not part of timber's primary API.
|
|
26
|
+
// They exist so that libraries importing from 'next/navigation' still work.
|
|
27
|
+
export { permanentRedirect, notFound } from '../server/primitives.js';
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny typed state machine utility.
|
|
3
|
+
*
|
|
4
|
+
* Enforces discriminated-union states, typed transitions with runtime
|
|
5
|
+
* guards, subscribe for external store integration, and assertPhase
|
|
6
|
+
* for function entry guards.
|
|
7
|
+
*
|
|
8
|
+
* Designed for 3–5 state consumers (stream transforms, client navigation,
|
|
9
|
+
* build phase sequencing). No async, no hierarchy, no history.
|
|
10
|
+
*
|
|
11
|
+
* Performance: send() is one object lookup + one function call.
|
|
12
|
+
* Equivalent cost to a boolean check after V8 inlining.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** A state machine instance with typed state and events. */
|
|
16
|
+
export interface Machine<TState extends { phase: string }, TEvent extends { type: string }> {
|
|
17
|
+
/** Current state (discriminated union — narrowed by phase). */
|
|
18
|
+
readonly state: TState;
|
|
19
|
+
|
|
20
|
+
/** Transition with runtime guard. Throws on invalid source+event pair. */
|
|
21
|
+
send(event: TEvent): void;
|
|
22
|
+
|
|
23
|
+
/** Subscribe to state changes. Returns unsubscribe function. */
|
|
24
|
+
subscribe(listener: (state: TState) => void): () => void;
|
|
25
|
+
|
|
26
|
+
/** Throw if not in the expected phase. Entry guard for functions. */
|
|
27
|
+
assertPhase<P extends TState['phase']>(phase: P): void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Transition map: `transitions[phase][eventType]` returns the next state.
|
|
32
|
+
*
|
|
33
|
+
* Each handler receives the current state (narrowed by phase context)
|
|
34
|
+
* and the event, returning the new state.
|
|
35
|
+
*/
|
|
36
|
+
export type TransitionMap<TState extends { phase: string }, TEvent extends { type: string }> = {
|
|
37
|
+
[P in TState['phase']]?: {
|
|
38
|
+
[E in TEvent['type']]?: (
|
|
39
|
+
state: Extract<TState, { phase: P }>,
|
|
40
|
+
event: Extract<TEvent, { type: E }>
|
|
41
|
+
) => TState;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export interface MachineConfig<TState extends { phase: string }, TEvent extends { type: string }> {
|
|
46
|
+
initial: TState;
|
|
47
|
+
transitions: TransitionMap<TState, TEvent>;
|
|
48
|
+
/** Fires after every valid transition. Use for side effects. */
|
|
49
|
+
onTransition?: (prev: TState, next: TState, event: TEvent) => void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Create a state machine from a config.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* type State = { phase: 'idle' } | { phase: 'running'; pid: number };
|
|
58
|
+
* type Event = { type: 'START'; pid: number } | { type: 'STOP' };
|
|
59
|
+
*
|
|
60
|
+
* const m = createMachine<State, Event>({
|
|
61
|
+
* initial: { phase: 'idle' },
|
|
62
|
+
* transitions: {
|
|
63
|
+
* idle: { START: (_s, e) => ({ phase: 'running', pid: e.pid }) },
|
|
64
|
+
* running: { STOP: () => ({ phase: 'idle' }) },
|
|
65
|
+
* },
|
|
66
|
+
* });
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export function createMachine<TState extends { phase: string }, TEvent extends { type: string }>(
|
|
70
|
+
config: MachineConfig<TState, TEvent>
|
|
71
|
+
): Machine<TState, TEvent> {
|
|
72
|
+
let current: TState = config.initial;
|
|
73
|
+
const listeners = new Set<(state: TState) => void>();
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
get state() {
|
|
77
|
+
return current;
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
send(event: TEvent): void {
|
|
81
|
+
const phaseHandlers = config.transitions[current.phase as TState['phase']];
|
|
82
|
+
const handler = phaseHandlers?.[event.type as TEvent['type']] as
|
|
83
|
+
| ((state: TState, event: TEvent) => TState)
|
|
84
|
+
| undefined;
|
|
85
|
+
|
|
86
|
+
if (!handler) {
|
|
87
|
+
throw new Error(`[state-machine] Invalid transition: ${current.phase} + ${event.type}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const prev = current;
|
|
91
|
+
current = handler(prev, event);
|
|
92
|
+
|
|
93
|
+
config.onTransition?.(prev, current, event);
|
|
94
|
+
|
|
95
|
+
for (const listener of listeners) {
|
|
96
|
+
listener(current);
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
subscribe(listener: (state: TState) => void): () => void {
|
|
101
|
+
listeners.add(listener);
|
|
102
|
+
return () => listeners.delete(listener);
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
assertPhase<P extends TState['phase']>(phase: P): void {
|
|
106
|
+
if (current.phase !== phase) {
|
|
107
|
+
throw new Error(`[state-machine] Expected phase "${phase}", got "${current.phase}"`);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|