@timber-js/app 0.2.0-alpha.98 → 0.2.0-alpha.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/dist/_chunks/actions-CQ8Z8VGL.js +1061 -0
- package/dist/_chunks/actions-CQ8Z8VGL.js.map +1 -0
- package/dist/_chunks/build-output-helper-DXnW0qjz.js +61 -0
- package/dist/_chunks/build-output-helper-DXnW0qjz.js.map +1 -0
- package/dist/_chunks/{define-Itxvcd7F.js → define-B-Q_UMOD.js} +19 -23
- package/dist/_chunks/define-B-Q_UMOD.js.map +1 -0
- package/dist/_chunks/{define-C77ScO0m.js → define-CfBPoJb0.js} +24 -7
- package/dist/_chunks/define-CfBPoJb0.js.map +1 -0
- package/dist/_chunks/define-cookie-BjpIt4UC.js +194 -0
- package/dist/_chunks/define-cookie-BjpIt4UC.js.map +1 -0
- package/dist/_chunks/{format-CYBGxKtc.js → format-Bcn-Iv1x.js} +1 -1
- package/dist/_chunks/{format-CYBGxKtc.js.map → format-Bcn-Iv1x.js.map} +1 -1
- package/dist/_chunks/handler-store-B-lqaGyh.js +54 -0
- package/dist/_chunks/handler-store-B-lqaGyh.js.map +1 -0
- package/dist/_chunks/logger-0m8MsKdc.js +291 -0
- package/dist/_chunks/logger-0m8MsKdc.js.map +1 -0
- package/dist/_chunks/merge-search-params-BphMdht_.js +122 -0
- package/dist/_chunks/merge-search-params-BphMdht_.js.map +1 -0
- package/dist/_chunks/navigation-root-BCYczjml.js +96 -0
- package/dist/_chunks/navigation-root-BCYczjml.js.map +1 -0
- package/dist/_chunks/registry-I2ss-lvy.js +20 -0
- package/dist/_chunks/registry-I2ss-lvy.js.map +1 -0
- package/dist/_chunks/router-ref-h3-UaCQv.js +28 -0
- package/dist/_chunks/router-ref-h3-UaCQv.js.map +1 -0
- package/dist/_chunks/{schema-bridge-C3xl_vfb.js → schema-bridge-Cxu4l-7p.js} +1 -1
- package/dist/_chunks/{schema-bridge-C3xl_vfb.js.map → schema-bridge-Cxu4l-7p.js.map} +1 -1
- package/dist/_chunks/{segment-context-fHFLF1PE.js → segment-context-Dx_OizxD.js} +1 -1
- package/dist/_chunks/{segment-context-fHFLF1PE.js.map → segment-context-Dx_OizxD.js.map} +1 -1
- package/dist/_chunks/{router-ref-C8OCm7g7.js → ssr-data-B4CdH7rE.js} +2 -26
- package/dist/_chunks/ssr-data-B4CdH7rE.js.map +1 -0
- package/dist/_chunks/{stale-reload-BX5gL1r-.js → stale-reload-Bab885FO.js} +1 -1
- package/dist/_chunks/{stale-reload-BX5gL1r-.js.map → stale-reload-Bab885FO.js.map} +1 -1
- package/dist/_chunks/tracing-C8V-YGsP.js +329 -0
- package/dist/_chunks/tracing-C8V-YGsP.js.map +1 -0
- package/dist/_chunks/{use-query-states-BiV5GJgm.js → use-query-states-B2XTqxDR.js} +3 -19
- package/dist/_chunks/use-query-states-B2XTqxDR.js.map +1 -0
- package/dist/_chunks/{use-params-IOPu7E8t.js → use-segment-params-BkpKAQ7D.js} +9 -95
- package/dist/_chunks/use-segment-params-BkpKAQ7D.js.map +1 -0
- package/dist/_chunks/{walkers-VOXgavMF.js → walkers-Tg0Alwcg.js} +6 -3
- package/dist/_chunks/walkers-Tg0Alwcg.js.map +1 -0
- package/dist/_chunks/{dev-warnings-DpGRGoDi.js → warnings-Cg47l5sk.js} +3 -3
- package/dist/_chunks/warnings-Cg47l5sk.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts +28 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -0
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +8 -28
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +8 -26
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +16 -0
- package/dist/adapters/shared.d.ts.map +1 -0
- package/dist/cache/index.js +9 -2
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/client/error-boundary.js +2 -1
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/form.d.ts +10 -24
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -5
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +40 -90
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +2 -1
- package/dist/client/internal.d.ts.map +1 -1
- package/dist/client/internal.js +81 -7
- package/dist/client/internal.js.map +1 -1
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/state.d.ts +1 -1
- package/dist/client/use-cookie.d.ts +8 -0
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +1 -1
- package/dist/client/use-segment-params.d.ts.map +1 -0
- package/dist/codec.d.ts +1 -1
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +2 -2
- package/dist/config-types.d.ts +28 -0
- package/dist/config-types.d.ts.map +1 -1
- package/dist/cookies/define-cookie.d.ts +87 -35
- 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 +48 -2
- package/dist/cookies/index.js.map +1 -0
- 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 +46 -0
- package/dist/cookies/validation.d.ts.map +1 -0
- package/dist/{plugins/dev-404-page.d.ts → dev-tools/404-page.d.ts} +1 -1
- package/dist/dev-tools/404-page.d.ts.map +1 -0
- package/dist/{plugins/dev-browser-logs.d.ts → dev-tools/browser-logs.d.ts} +1 -1
- package/dist/dev-tools/browser-logs.d.ts.map +1 -0
- package/dist/{plugins/dev-error-page.d.ts → dev-tools/error-page.d.ts} +2 -2
- package/dist/dev-tools/error-page.d.ts.map +1 -0
- package/dist/{server/dev-holding-server.d.ts → dev-tools/holding-server.d.ts} +1 -1
- package/dist/dev-tools/holding-server.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/{server/dev-span-processor.d.ts → dev-tools/instrumentation.d.ts} +26 -6
- 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} +1 -1
- package/dist/dev-tools/logs.d.ts.map +1 -0
- package/dist/{plugins/dev-error-overlay.d.ts → dev-tools/overlay.d.ts} +3 -12
- 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/{plugins/dev-terminal-error.d.ts → dev-tools/terminal.d.ts} +2 -2
- package/dist/dev-tools/terminal.d.ts.map +1 -0
- package/dist/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +1 -1
- package/dist/dev-tools/warnings.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +97 -72
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +1 -1
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts.map +1 -1
- package/dist/routing/index.js +1 -1
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/status-file-lint.d.ts.map +1 -1
- package/dist/search-params/define.d.ts +25 -7
- package/dist/search-params/define.d.ts.map +1 -1
- package/dist/search-params/index.js +5 -3
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/wrappers.d.ts +2 -2
- package/dist/search-params/wrappers.d.ts.map +1 -1
- package/dist/segment-params/define.d.ts +23 -6
- package/dist/segment-params/define.d.ts.map +1 -1
- package/dist/segment-params/index.js +1 -1
- package/dist/server/access-gate.d.ts +4 -3
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-handler.d.ts +15 -6
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +5 -5
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/asset-headers.d.ts +1 -15
- package/dist/server/asset-headers.d.ts.map +1 -1
- 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 +51 -0
- package/dist/server/cookie-parsing.d.ts.map +1 -0
- package/dist/server/deny-boundary.d.ts +90 -0
- package/dist/server/deny-boundary.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/early-hints-sender.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -4
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -149
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +6 -4
- package/dist/server/internal.d.ts.map +1 -1
- package/dist/server/internal.js +261 -408
- package/dist/server/internal.js.map +1 -1
- package/dist/server/logger.d.ts +14 -0
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +17 -0
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/param-coercion.d.ts +26 -0
- package/dist/server/param-coercion.d.ts.map +1 -0
- package/dist/server/pipeline-helpers.d.ts +14 -7
- package/dist/server/pipeline-helpers.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 +4 -49
- package/dist/server/pipeline-phases.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +0 -2
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/request-context.d.ts +22 -159
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.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/helpers.d.ts +1 -1
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts +50 -0
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +59 -14
- package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -1
- package/dist/server/state-tree-diff.d.ts.map +1 -1
- package/dist/server/tracing.d.ts +1 -1
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +45 -16
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +48 -0
- 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/shims/headers.d.ts +2 -2
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +3 -1
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +9 -4
- package/dist/shims/navigation.d.ts.map +1 -1
- package/package.json +6 -7
- package/src/adapters/build-output-helper.ts +77 -0
- package/src/adapters/cloudflare.ts +10 -50
- package/src/adapters/nitro.ts +11 -45
- package/src/adapters/shared.ts +40 -0
- package/src/cache/timber-cache.ts +3 -2
- package/src/cli.ts +0 -0
- package/src/client/form.tsx +17 -25
- package/src/client/index.ts +16 -9
- package/src/client/internal.ts +3 -2
- package/src/client/router.ts +1 -1
- package/src/client/rsc-fetch.ts +15 -0
- package/src/client/state.ts +2 -2
- package/src/client/use-cookie.ts +29 -0
- package/src/codec.ts +3 -7
- package/src/config-types.ts +28 -0
- package/src/cookies/define-cookie.ts +271 -78
- package/src/cookies/index.ts +11 -8
- package/src/cookies/json-cookie.ts +105 -0
- package/src/cookies/validation.ts +134 -0
- package/src/{plugins/dev-404-page.ts → dev-tools/404-page.ts} +2 -7
- package/src/{plugins/dev-error-page.ts → dev-tools/error-page.ts} +5 -32
- package/src/dev-tools/index.ts +90 -0
- package/src/dev-tools/instrumentation.ts +176 -0
- package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +2 -2
- package/src/{plugins/dev-error-overlay.ts → dev-tools/overlay.ts} +5 -23
- package/src/dev-tools/stack-classifier.ts +75 -0
- package/src/{plugins/dev-terminal-error.ts → dev-tools/terminal.ts} +4 -38
- package/src/{server/dev-warnings.ts → dev-tools/warnings.ts} +1 -1
- package/src/index.ts +11 -3
- package/src/plugin-context.ts +1 -1
- package/src/plugins/adapter-build.ts +3 -1
- package/src/plugins/dev-server.ts +3 -3
- package/src/plugins/shims.ts +1 -1
- package/src/plugins/static-build.ts +1 -1
- package/src/routing/convention-lint.ts +5 -4
- package/src/routing/scanner.ts +5 -2
- package/src/routing/status-file-lint.ts +4 -2
- package/src/search-params/define.ts +71 -15
- package/src/search-params/wrappers.ts +9 -2
- package/src/segment-params/define.ts +66 -13
- package/src/server/access-gate.tsx +9 -8
- package/src/server/action-handler.ts +28 -38
- package/src/server/als-registry.ts +5 -5
- package/src/server/asset-headers.ts +8 -34
- package/src/server/cookie-context.ts +468 -0
- package/src/server/cookie-parsing.ts +135 -0
- package/src/server/{deny-page-resolver.ts → deny-boundary.ts} +78 -14
- package/src/server/deny-renderer.ts +2 -7
- package/src/server/early-hints-sender.ts +3 -2
- package/src/server/fallback-error.ts +1 -1
- package/src/server/index.ts +13 -14
- package/src/server/internal.ts +10 -3
- package/src/server/logger.ts +23 -0
- package/src/server/middleware-runner.ts +44 -0
- package/src/server/param-coercion.ts +76 -0
- package/src/server/pipeline-helpers.ts +37 -13
- package/src/server/pipeline-outcome.ts +167 -0
- package/src/server/pipeline-phases.ts +27 -209
- package/src/server/pipeline.ts +2 -9
- package/src/server/request-context.ts +46 -451
- package/src/server/route-element-builder.ts +7 -3
- package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
- package/src/server/rsc-entry/error-renderer.ts +1 -1
- package/src/server/rsc-entry/helpers.ts +2 -7
- package/src/server/rsc-entry/index.ts +34 -273
- package/src/server/rsc-entry/render-route.ts +304 -0
- package/src/server/rsc-entry/rsc-payload.ts +1 -1
- package/src/server/rsc-entry/ssr-renderer.ts +2 -2
- package/src/server/rsc-entry/wrap-action-dispatch.ts +316 -23
- package/src/server/ssr-entry.ts +1 -1
- package/src/server/state-tree-diff.ts +4 -1
- package/src/server/tracing.ts +3 -3
- package/src/server/tree-builder.ts +128 -52
- package/src/server/types.ts +52 -0
- package/src/server/utils/escape-html.ts +20 -0
- package/src/shims/headers.ts +3 -3
- package/src/shims/navigation-client.ts +4 -3
- package/src/shims/navigation.ts +9 -7
- package/dist/_chunks/actions-DLnUaR65.js +0 -421
- package/dist/_chunks/actions-DLnUaR65.js.map +0 -1
- package/dist/_chunks/als-registry-HS0LGUl2.js +0 -41
- package/dist/_chunks/als-registry-HS0LGUl2.js.map +0 -1
- package/dist/_chunks/debug-ECi_61pb.js +0 -108
- package/dist/_chunks/debug-ECi_61pb.js.map +0 -1
- package/dist/_chunks/define-C77ScO0m.js.map +0 -1
- package/dist/_chunks/define-Itxvcd7F.js.map +0 -1
- package/dist/_chunks/define-cookie-BowvzoP0.js +0 -94
- package/dist/_chunks/define-cookie-BowvzoP0.js.map +0 -1
- package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +0 -1
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js +0 -41
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +0 -1
- package/dist/_chunks/request-context-CK5tZqIP.js +0 -478
- package/dist/_chunks/request-context-CK5tZqIP.js.map +0 -1
- package/dist/_chunks/router-ref-C8OCm7g7.js.map +0 -1
- package/dist/_chunks/tracing-CCYbKn5n.js +0 -238
- package/dist/_chunks/tracing-CCYbKn5n.js.map +0 -1
- package/dist/_chunks/use-params-IOPu7E8t.js.map +0 -1
- package/dist/_chunks/use-query-states-BiV5GJgm.js.map +0 -1
- package/dist/_chunks/walkers-VOXgavMF.js.map +0 -1
- package/dist/client/use-params.d.ts.map +0 -1
- package/dist/plugins/dev-404-page.d.ts.map +0 -1
- package/dist/plugins/dev-browser-logs.d.ts.map +0 -1
- package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
- package/dist/plugins/dev-error-page.d.ts.map +0 -1
- package/dist/plugins/dev-logs.d.ts.map +0 -1
- package/dist/plugins/dev-terminal-error.d.ts.map +0 -1
- package/dist/server/deny-page-resolver.d.ts +0 -52
- package/dist/server/deny-page-resolver.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-holding-server.d.ts.map +0 -1
- package/dist/server/dev-logger.d.ts.map +0 -1
- package/dist/server/dev-span-processor.d.ts.map +0 -1
- package/dist/server/dev-warnings.d.ts.map +0 -1
- package/dist/server/page-deny-boundary.d.ts +0 -31
- package/dist/server/page-deny-boundary.d.ts.map +0 -1
- package/src/server/dev-fetch-instrumentation.ts +0 -96
- package/src/server/dev-span-processor.ts +0 -78
- package/src/server/page-deny-boundary.tsx +0 -56
- /package/src/client/{use-params.ts → use-segment-params.ts} +0 -0
- /package/src/{plugins/dev-browser-logs.ts → dev-tools/browser-logs.ts} +0 -0
- /package/src/{server/dev-holding-server.ts → dev-tools/holding-server.ts} +0 -0
- /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline outcome translator — converts a `PhaseOutcome` (the value
|
|
3
|
+
* each phase function returns) into a final `Response`.
|
|
4
|
+
*
|
|
5
|
+
* Lifted out of `pipeline-phases.ts` (TIM-853) so the per-phase try /
|
|
6
|
+
* catch logic and the terminal Response-building logic each live in
|
|
7
|
+
* their own file. The phases produce values; this module is the single
|
|
8
|
+
* source of truth for how those values become wire responses.
|
|
9
|
+
*
|
|
10
|
+
* See design/07-routing.md §"Request Lifecycle".
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
applyCookieJar,
|
|
15
|
+
buildRedirectResponse,
|
|
16
|
+
cloneWithMutableHeaders,
|
|
17
|
+
fireOnRequestError,
|
|
18
|
+
mergeMissingHeaders,
|
|
19
|
+
} from './pipeline-helpers.js';
|
|
20
|
+
import {
|
|
21
|
+
logProxyError,
|
|
22
|
+
logMiddlewareError,
|
|
23
|
+
logMiddlewareShortCircuit,
|
|
24
|
+
logRenderError,
|
|
25
|
+
} from './logger.js';
|
|
26
|
+
import { markResponseFlushed } from './request-context.js';
|
|
27
|
+
import { RedirectSignal, DenySignal } from './primitives.js';
|
|
28
|
+
import type { PipelineConfig, RouteMatch } from './pipeline.js';
|
|
29
|
+
|
|
30
|
+
// ─── Phase Outcome ─────────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
export type PhaseName = 'proxy' | 'middleware' | 'render';
|
|
33
|
+
|
|
34
|
+
export type PhaseOutcome =
|
|
35
|
+
| { kind: 'response'; phase: PhaseName; response: Response }
|
|
36
|
+
| { kind: 'redirect'; phase: PhaseName; signal: RedirectSignal }
|
|
37
|
+
| { kind: 'deny'; phase: PhaseName; signal: DenySignal }
|
|
38
|
+
| { kind: 'error'; phase: PhaseName; error: unknown };
|
|
39
|
+
|
|
40
|
+
export interface OutcomeContext {
|
|
41
|
+
req: Request;
|
|
42
|
+
method: string;
|
|
43
|
+
path: string;
|
|
44
|
+
responseHeaders?: Headers;
|
|
45
|
+
match?: RouteMatch;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ─── Translator ────────────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Terminal outcome handler — converts a `PhaseOutcome` into a final
|
|
52
|
+
* `Response`, applying cookies, building redirects, rendering deny pages
|
|
53
|
+
* and fallback error pages, and firing instrumentation hooks.
|
|
54
|
+
*
|
|
55
|
+
* This is the single source of truth for how phase outputs become wire
|
|
56
|
+
* responses; the per-phase try/catch blocks now produce values, not
|
|
57
|
+
* Responses, so the conversion logic lives in exactly one place.
|
|
58
|
+
*/
|
|
59
|
+
export async function outcomeToResponse(
|
|
60
|
+
config: PipelineConfig,
|
|
61
|
+
outcome: PhaseOutcome,
|
|
62
|
+
ctx: OutcomeContext
|
|
63
|
+
): Promise<Response> {
|
|
64
|
+
switch (outcome.kind) {
|
|
65
|
+
case 'response': {
|
|
66
|
+
// Clone unconditionally so downstream code (cookie/header merge,
|
|
67
|
+
// Server-Timing in createPipeline) can write headers without paying
|
|
68
|
+
// for a try/catch immutability probe per request. User middleware,
|
|
69
|
+
// proxy, and route code may all return `Response.redirect()` or
|
|
70
|
+
// platform-level responses with frozen header bags. See TIM-866.
|
|
71
|
+
const finalResponse = cloneWithMutableHeaders(outcome.response);
|
|
72
|
+
|
|
73
|
+
if (outcome.phase === 'proxy') return finalResponse;
|
|
74
|
+
|
|
75
|
+
if (outcome.phase === 'middleware' && ctx.responseHeaders) {
|
|
76
|
+
applyCookieJar(finalResponse.headers);
|
|
77
|
+
mergeMissingHeaders(finalResponse.headers, ctx.responseHeaders);
|
|
78
|
+
logMiddlewareShortCircuit({
|
|
79
|
+
method: ctx.method,
|
|
80
|
+
path: ctx.path,
|
|
81
|
+
status: finalResponse.status,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (outcome.phase === 'render') {
|
|
86
|
+
markResponseFlushed();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return finalResponse;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
case 'redirect': {
|
|
93
|
+
const headers = ctx.responseHeaders ?? new Headers();
|
|
94
|
+
applyCookieJar(headers);
|
|
95
|
+
return buildRedirectResponse(outcome.signal, ctx.req, headers);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
case 'deny': {
|
|
99
|
+
const headers = ctx.responseHeaders ?? new Headers();
|
|
100
|
+
applyCookieJar(headers);
|
|
101
|
+
if (config.renderDenyFallback) {
|
|
102
|
+
try {
|
|
103
|
+
// Clone user-supplied deny-page responses so downstream
|
|
104
|
+
// Server-Timing writes are safe against frozen header bags
|
|
105
|
+
// (e.g. user returned Response.redirect from the hook).
|
|
106
|
+
return cloneWithMutableHeaders(
|
|
107
|
+
await config.renderDenyFallback(outcome.signal, ctx.req, headers, ctx.match)
|
|
108
|
+
);
|
|
109
|
+
} catch (denyRenderError) {
|
|
110
|
+
// Deny page rendering failed — log before falling through to bare response.
|
|
111
|
+
// Without this, a crashing deny page produces a blank response with zero
|
|
112
|
+
// server-side signal. See TIM-876.
|
|
113
|
+
logRenderError({ method: ctx.method, path: ctx.path, error: denyRenderError });
|
|
114
|
+
await fireOnRequestError(denyRenderError, ctx.req, 'render');
|
|
115
|
+
if (config.onPipelineError && denyRenderError instanceof Error)
|
|
116
|
+
config.onPipelineError(denyRenderError, 'render');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return new Response(null, { status: outcome.signal.status, headers });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
case 'error': {
|
|
123
|
+
if (outcome.phase === 'proxy') {
|
|
124
|
+
logProxyError({ error: outcome.error });
|
|
125
|
+
await fireOnRequestError(outcome.error, ctx.req, 'proxy');
|
|
126
|
+
if (config.onPipelineError && outcome.error instanceof Error)
|
|
127
|
+
config.onPipelineError(outcome.error, 'proxy');
|
|
128
|
+
return new Response(null, { status: 500 });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (outcome.phase === 'middleware') {
|
|
132
|
+
logMiddlewareError({ method: ctx.method, path: ctx.path, error: outcome.error });
|
|
133
|
+
await fireOnRequestError(outcome.error, ctx.req, 'handler');
|
|
134
|
+
if (config.onPipelineError && outcome.error instanceof Error) {
|
|
135
|
+
config.onPipelineError(outcome.error, 'middleware');
|
|
136
|
+
}
|
|
137
|
+
return new Response(null, { status: 500 });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const headers = ctx.responseHeaders ?? new Headers();
|
|
141
|
+
applyCookieJar(headers);
|
|
142
|
+
logRenderError({ method: ctx.method, path: ctx.path, error: outcome.error });
|
|
143
|
+
await fireOnRequestError(outcome.error, ctx.req, 'render');
|
|
144
|
+
if (config.onPipelineError && outcome.error instanceof Error)
|
|
145
|
+
config.onPipelineError(outcome.error, 'render');
|
|
146
|
+
if (config.renderFallbackError) {
|
|
147
|
+
try {
|
|
148
|
+
// Clone user-supplied fallback error responses so downstream
|
|
149
|
+
// Server-Timing writes are safe against frozen header bags.
|
|
150
|
+
return cloneWithMutableHeaders(
|
|
151
|
+
await config.renderFallbackError(outcome.error, ctx.req, headers)
|
|
152
|
+
);
|
|
153
|
+
} catch (fallbackRenderError) {
|
|
154
|
+
// Fallback rendering itself failed — log the secondary error before
|
|
155
|
+
// falling through to bare 500. The original render error was already
|
|
156
|
+
// logged above; this captures the fallback renderer's own crash so it
|
|
157
|
+
// doesn't vanish silently. See TIM-876.
|
|
158
|
+
logRenderError({ method: ctx.method, path: ctx.path, error: fallbackRenderError });
|
|
159
|
+
await fireOnRequestError(fallbackRenderError, ctx.req, 'render');
|
|
160
|
+
if (config.onPipelineError && fallbackRenderError instanceof Error)
|
|
161
|
+
config.onPipelineError(fallbackRenderError, 'render');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return new Response(null, { status: 500 });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pipeline phase functions — module-level free functions that take their
|
|
3
3
|
* dependencies as explicit parameters. Each phase returns a `PhaseOutcome`
|
|
4
|
-
* (a discriminated union over response / redirect / deny / error)
|
|
5
|
-
* terminal `outcomeToResponse`
|
|
4
|
+
* (a discriminated union over response / redirect / deny / error) defined
|
|
5
|
+
* in `pipeline-outcome.ts`. The terminal `outcomeToResponse` (also in
|
|
6
|
+
* `pipeline-outcome.ts`) translates outcomes into Responses.
|
|
6
7
|
*
|
|
7
8
|
* Lifted out of `createPipeline` so each phase can be unit-tested in
|
|
8
9
|
* isolation. The lift is mechanical — these functions used to be closures
|
|
@@ -13,118 +14,33 @@
|
|
|
13
14
|
|
|
14
15
|
import { canonicalize } from './canonicalize.js';
|
|
15
16
|
import { runProxy } from './proxy.js';
|
|
16
|
-
import { runMiddlewareChain } from './middleware-runner.js';
|
|
17
|
+
import { runMiddlewareChain, shouldBypassMiddleware } from './middleware-runner.js';
|
|
17
18
|
import { withTiming } from './server-timing.js';
|
|
18
19
|
import {
|
|
19
20
|
applyRequestHeaderOverlay,
|
|
20
21
|
setMutableCookieContext,
|
|
21
|
-
markResponseFlushed,
|
|
22
22
|
setSegmentParams,
|
|
23
23
|
} from './request-context.js';
|
|
24
24
|
import { withSpan } from './tracing.js';
|
|
25
|
-
import {
|
|
26
|
-
logProxyError,
|
|
27
|
-
logMiddlewareError,
|
|
28
|
-
logMiddlewareShortCircuit,
|
|
29
|
-
logRenderError,
|
|
30
|
-
} from './logger.js';
|
|
25
|
+
import { logRenderError } from './logger.js';
|
|
31
26
|
import { RedirectSignal, DenySignal } from './primitives.js';
|
|
32
27
|
import { ParamCoercionError } from './route-element-builder.js';
|
|
33
28
|
import { checkVersionSkew, applyReloadHeaders } from './version-skew.js';
|
|
34
29
|
import { serveStaticMetadataFile, serializeSitemap } from './pipeline-metadata.js';
|
|
35
30
|
import { loadModule } from './safe-load.js';
|
|
36
31
|
import { findInterceptionMatch } from './pipeline-interception.js';
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
cloneWithMutableHeaders,
|
|
41
|
-
fireOnRequestError,
|
|
42
|
-
mergeMissingHeaders,
|
|
43
|
-
safeMerge,
|
|
44
|
-
type ProxyResolver,
|
|
45
|
-
} from './pipeline-helpers.js';
|
|
32
|
+
import { applyCookieJar, cloneWithMutableHeaders, type ProxyResolver } from './pipeline-helpers.js';
|
|
33
|
+
import { coerceSegmentParams } from './param-coercion.js';
|
|
34
|
+
import { outcomeToResponse, type PhaseOutcome } from './pipeline-outcome.js';
|
|
46
35
|
import type { InterceptionContext, PipelineConfig, RouteMatch } from './pipeline.js';
|
|
47
|
-
import type { MiddlewareContext } from './types.js';
|
|
48
|
-
|
|
49
|
-
// ─── Phase Outcome ─────────────────────────────────────────────────────────
|
|
50
|
-
|
|
51
|
-
export type PhaseName = 'proxy' | 'middleware' | 'render';
|
|
52
|
-
|
|
53
|
-
export type PhaseOutcome =
|
|
54
|
-
| { kind: 'response'; phase: PhaseName; response: Response }
|
|
55
|
-
| { kind: 'redirect'; phase: PhaseName; signal: RedirectSignal }
|
|
56
|
-
| { kind: 'deny'; phase: PhaseName; signal: DenySignal }
|
|
57
|
-
| { kind: 'error'; phase: PhaseName; error: unknown };
|
|
58
|
-
|
|
59
|
-
export interface OutcomeContext {
|
|
60
|
-
req: Request;
|
|
61
|
-
method: string;
|
|
62
|
-
path: string;
|
|
63
|
-
responseHeaders?: Headers;
|
|
64
|
-
match?: RouteMatch;
|
|
65
|
-
}
|
|
36
|
+
import type { MetadataHandler, MetadataRoute, MiddlewareContext } from './types.js';
|
|
37
|
+
import { swallow } from './logger.js';
|
|
66
38
|
|
|
67
39
|
interface RenderContext {
|
|
68
40
|
canonicalPathname: string;
|
|
69
41
|
interception?: InterceptionContext;
|
|
70
42
|
}
|
|
71
43
|
|
|
72
|
-
// ─── Param Coercion ────────────────────────────────────────────────────────
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Run segment param coercion on the matched route's segments.
|
|
76
|
-
*
|
|
77
|
-
* Loads params.ts modules from segments that have them, extracts the
|
|
78
|
-
* segmentParams definition, and coerces raw string params through codecs.
|
|
79
|
-
* Throws ParamCoercionError if any codec fails (→ 404).
|
|
80
|
-
*
|
|
81
|
-
* This runs BEFORE middleware, so ctx.segmentParams is already typed.
|
|
82
|
-
* See design/07-routing.md §"Where Coercion Runs"
|
|
83
|
-
*/
|
|
84
|
-
export async function coerceSegmentParams(match: RouteMatch): Promise<void> {
|
|
85
|
-
const segments = match.segments;
|
|
86
|
-
let mergeTarget = match.segmentParams as Record<string, unknown>;
|
|
87
|
-
let usesNullPrototypeTarget = Object.getPrototypeOf(mergeTarget) === null;
|
|
88
|
-
|
|
89
|
-
for (const segment of segments) {
|
|
90
|
-
// Only process segments that have a params.ts convention file
|
|
91
|
-
if (!segment.params) continue;
|
|
92
|
-
|
|
93
|
-
let mod: Record<string, unknown>;
|
|
94
|
-
try {
|
|
95
|
-
mod = await loadModule(segment.params);
|
|
96
|
-
} catch (err) {
|
|
97
|
-
throw new ParamCoercionError(
|
|
98
|
-
`Failed to load params module for segment "${segment.segmentName}": ${err instanceof Error ? err.message : String(err)}`
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const segmentParamsDef = mod.segmentParams as
|
|
103
|
-
| { parse(raw: Record<string, string | string[]>): Record<string, unknown> }
|
|
104
|
-
| undefined;
|
|
105
|
-
|
|
106
|
-
if (!segmentParamsDef || typeof segmentParamsDef.parse !== 'function') continue;
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
const coerced = segmentParamsDef.parse(match.segmentParams);
|
|
110
|
-
|
|
111
|
-
if (!usesNullPrototypeTarget) {
|
|
112
|
-
mergeTarget = Object.create(null) as Record<string, unknown>;
|
|
113
|
-
safeMerge(mergeTarget, match.segmentParams as Record<string, unknown>);
|
|
114
|
-
match.segmentParams = mergeTarget as RouteMatch['segmentParams'];
|
|
115
|
-
usesNullPrototypeTarget = true;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// safeMerge blocks shallow prototype-polluting keys from codec output.
|
|
119
|
-
// The null-prototype target above provides the deeper guarantee for
|
|
120
|
-
// nested values without paying the cost of a deep sanitizer.
|
|
121
|
-
safeMerge(mergeTarget, coerced as Record<string, unknown>);
|
|
122
|
-
} catch (err) {
|
|
123
|
-
throw new ParamCoercionError(err instanceof Error ? err.message : String(err));
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
44
|
// ─── Phase: Proxy ──────────────────────────────────────────────────────────
|
|
129
45
|
|
|
130
46
|
/**
|
|
@@ -307,7 +223,7 @@ export async function handleRequest(
|
|
|
307
223
|
return await serveStaticMetadataFile(metaMatch);
|
|
308
224
|
}
|
|
309
225
|
|
|
310
|
-
const mod = await loadModule<{ default?:
|
|
226
|
+
const mod = await loadModule<{ default?: MetadataHandler }>(metaMatch.file);
|
|
311
227
|
if (typeof mod.default !== 'function') {
|
|
312
228
|
return new Response('Metadata route must export a default function', { status: 500 });
|
|
313
229
|
}
|
|
@@ -318,17 +234,21 @@ export async function handleRequest(
|
|
|
318
234
|
if (handlerResult instanceof Response) {
|
|
319
235
|
return cloneWithMutableHeaders(handlerResult);
|
|
320
236
|
}
|
|
321
|
-
// Otherwise, serialize based on content type
|
|
237
|
+
// Otherwise, serialize based on content type. The type discriminator
|
|
238
|
+
// here is the metadata route's declared content type (from the file
|
|
239
|
+
// convention), not the shape of `handlerResult` — TS can't narrow the
|
|
240
|
+
// `MetadataResult` union on that, so we assert against the expected
|
|
241
|
+
// shape at each branch.
|
|
322
242
|
const contentType = metaMatch.contentType;
|
|
323
243
|
let body: string;
|
|
324
244
|
if (typeof handlerResult === 'string') {
|
|
325
245
|
body = handlerResult;
|
|
326
246
|
} else if (contentType === 'application/xml') {
|
|
327
|
-
body = serializeSitemap(handlerResult);
|
|
247
|
+
body = serializeSitemap(handlerResult as MetadataRoute.Sitemap);
|
|
328
248
|
} else if (contentType === 'application/manifest+json') {
|
|
329
249
|
body = JSON.stringify(handlerResult, null, 2);
|
|
330
250
|
} else {
|
|
331
|
-
body =
|
|
251
|
+
body = String(handlerResult);
|
|
332
252
|
}
|
|
333
253
|
return new Response(body, {
|
|
334
254
|
status: 200,
|
|
@@ -427,8 +347,8 @@ export async function handleRequest(
|
|
|
427
347
|
if (config.earlyHints) {
|
|
428
348
|
try {
|
|
429
349
|
await config.earlyHints(match, req, responseHeaders);
|
|
430
|
-
} catch {
|
|
431
|
-
|
|
350
|
+
} catch (err) {
|
|
351
|
+
swallow(err, 'early hints hook threw');
|
|
432
352
|
}
|
|
433
353
|
}
|
|
434
354
|
|
|
@@ -462,8 +382,14 @@ export async function handleRequest(
|
|
|
462
382
|
// See design/07-routing.md §"params.ts — Convention File for Typed Params"
|
|
463
383
|
setSegmentParams(match.segmentParams);
|
|
464
384
|
|
|
385
|
+
// Bypass middleware for synthetic re-render requests built by the
|
|
386
|
+
// action-dispatch wrapper after a no-JS form validation failure.
|
|
387
|
+
// The wrapper has already executed middleware once on the inbound POST;
|
|
388
|
+
// running it again on the rerender GET would double-execute auth, rate
|
|
389
|
+
// limiting, and request-header injection. See TIM-871.
|
|
390
|
+
const skipMiddleware = shouldBypassMiddleware(req);
|
|
465
391
|
const outcome =
|
|
466
|
-
match.middlewareChain.length > 0
|
|
392
|
+
!skipMiddleware && match.middlewareChain.length > 0
|
|
467
393
|
? await runMiddlewarePhase(config, req, match, responseHeaders, requestHeaderOverlay, {
|
|
468
394
|
canonicalPathname,
|
|
469
395
|
interception,
|
|
@@ -481,111 +407,3 @@ export async function handleRequest(
|
|
|
481
407
|
match,
|
|
482
408
|
});
|
|
483
409
|
}
|
|
484
|
-
|
|
485
|
-
// ─── Outcome Translation ───────────────────────────────────────────────────
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* Terminal outcome handler — converts a `PhaseOutcome` into a final
|
|
489
|
-
* `Response`, applying cookies, building redirects, rendering deny pages
|
|
490
|
-
* and fallback error pages, and firing instrumentation hooks.
|
|
491
|
-
*
|
|
492
|
-
* This is the single source of truth for how phase outputs become wire
|
|
493
|
-
* responses; the per-phase try/catch blocks now produce values, not
|
|
494
|
-
* Responses, so the conversion logic lives in exactly one place.
|
|
495
|
-
*/
|
|
496
|
-
export async function outcomeToResponse(
|
|
497
|
-
config: PipelineConfig,
|
|
498
|
-
outcome: PhaseOutcome,
|
|
499
|
-
ctx: OutcomeContext
|
|
500
|
-
): Promise<Response> {
|
|
501
|
-
switch (outcome.kind) {
|
|
502
|
-
case 'response': {
|
|
503
|
-
// Clone unconditionally so downstream code (cookie/header merge,
|
|
504
|
-
// Server-Timing in createPipeline) can write headers without paying
|
|
505
|
-
// for a try/catch immutability probe per request. User middleware,
|
|
506
|
-
// proxy, and route code may all return `Response.redirect()` or
|
|
507
|
-
// platform-level responses with frozen header bags. See TIM-866.
|
|
508
|
-
const finalResponse = cloneWithMutableHeaders(outcome.response);
|
|
509
|
-
|
|
510
|
-
if (outcome.phase === 'proxy') return finalResponse;
|
|
511
|
-
|
|
512
|
-
if (outcome.phase === 'middleware' && ctx.responseHeaders) {
|
|
513
|
-
applyCookieJar(finalResponse.headers);
|
|
514
|
-
mergeMissingHeaders(finalResponse.headers, ctx.responseHeaders);
|
|
515
|
-
logMiddlewareShortCircuit({
|
|
516
|
-
method: ctx.method,
|
|
517
|
-
path: ctx.path,
|
|
518
|
-
status: finalResponse.status,
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
if (outcome.phase === 'render') {
|
|
523
|
-
markResponseFlushed();
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
return finalResponse;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
case 'redirect': {
|
|
530
|
-
const headers = ctx.responseHeaders ?? new Headers();
|
|
531
|
-
applyCookieJar(headers);
|
|
532
|
-
return buildRedirectResponse(outcome.signal, ctx.req, headers);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
case 'deny': {
|
|
536
|
-
const headers = ctx.responseHeaders ?? new Headers();
|
|
537
|
-
applyCookieJar(headers);
|
|
538
|
-
if (config.renderDenyFallback) {
|
|
539
|
-
try {
|
|
540
|
-
// Clone user-supplied deny-page responses so downstream
|
|
541
|
-
// Server-Timing writes are safe against frozen header bags
|
|
542
|
-
// (e.g. user returned Response.redirect from the hook).
|
|
543
|
-
return cloneWithMutableHeaders(
|
|
544
|
-
await config.renderDenyFallback(outcome.signal, ctx.req, headers, ctx.match)
|
|
545
|
-
);
|
|
546
|
-
} catch {
|
|
547
|
-
// Deny page rendering failed — fall through to bare response
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
return new Response(null, { status: outcome.signal.status, headers });
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
case 'error': {
|
|
554
|
-
if (outcome.phase === 'proxy') {
|
|
555
|
-
logProxyError({ error: outcome.error });
|
|
556
|
-
await fireOnRequestError(outcome.error, ctx.req, 'proxy');
|
|
557
|
-
if (config.onPipelineError && outcome.error instanceof Error)
|
|
558
|
-
config.onPipelineError(outcome.error, 'proxy');
|
|
559
|
-
return new Response(null, { status: 500 });
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
if (outcome.phase === 'middleware') {
|
|
563
|
-
logMiddlewareError({ method: ctx.method, path: ctx.path, error: outcome.error });
|
|
564
|
-
await fireOnRequestError(outcome.error, ctx.req, 'handler');
|
|
565
|
-
if (config.onPipelineError && outcome.error instanceof Error) {
|
|
566
|
-
config.onPipelineError(outcome.error, 'middleware');
|
|
567
|
-
}
|
|
568
|
-
return new Response(null, { status: 500 });
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
const headers = ctx.responseHeaders ?? new Headers();
|
|
572
|
-
applyCookieJar(headers);
|
|
573
|
-
logRenderError({ method: ctx.method, path: ctx.path, error: outcome.error });
|
|
574
|
-
await fireOnRequestError(outcome.error, ctx.req, 'render');
|
|
575
|
-
if (config.onPipelineError && outcome.error instanceof Error)
|
|
576
|
-
config.onPipelineError(outcome.error, 'render');
|
|
577
|
-
if (config.renderFallbackError) {
|
|
578
|
-
try {
|
|
579
|
-
// Clone user-supplied fallback error responses so downstream
|
|
580
|
-
// Server-Timing writes are safe against frozen header bags.
|
|
581
|
-
return cloneWithMutableHeaders(
|
|
582
|
-
await config.renderFallbackError(outcome.error, ctx.req, headers)
|
|
583
|
-
);
|
|
584
|
-
} catch {
|
|
585
|
-
// Fallback rendering itself failed — fall through to bare 500
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return new Response(null, { status: 500 });
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
}
|
package/src/server/pipeline.ts
CHANGED
|
@@ -31,15 +31,8 @@ import { logRequestReceived, logRequestCompleted, logSlowRequest } from './logge
|
|
|
31
31
|
import { DenySignal } from './primitives.js';
|
|
32
32
|
import type { ManifestSegmentNode } from './route-matcher.js';
|
|
33
33
|
import { makeProxyResolver } from './pipeline-helpers.js';
|
|
34
|
-
import { handleRequest,
|
|
35
|
-
|
|
36
|
-
// ─── Re-exports for backwards compatibility ────────────────────────────────
|
|
37
|
-
|
|
38
|
-
// `safeMerge` and `coerceSegmentParams` were originally exported from this
|
|
39
|
-
// module. They now live in pipeline-helpers.ts and pipeline-phases.ts; the
|
|
40
|
-
// re-exports preserve `import { safeMerge } from './pipeline.js'` callers.
|
|
41
|
-
export { safeMerge } from './pipeline-helpers.js';
|
|
42
|
-
export { coerceSegmentParams } from './pipeline-phases.js';
|
|
34
|
+
import { handleRequest, runProxyPhase } from './pipeline-phases.js';
|
|
35
|
+
import { outcomeToResponse } from './pipeline-outcome.js';
|
|
43
36
|
|
|
44
37
|
// ─── Route Match Result ────────────────────────────────────────────────────
|
|
45
38
|
|