@timber-js/app 0.2.0-alpha.186 → 0.2.0-alpha.187
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{actions-C-Rw9vPc.js → actions-35jnMdeJ.js} +4 -3
- package/dist/_chunks/{actions-C-Rw9vPc.js.map → actions-35jnMdeJ.js.map} +1 -1
- package/dist/_chunks/als-registry-C6kcfprT.js +41 -0
- package/dist/_chunks/als-registry-C6kcfprT.js.map +1 -0
- package/dist/_chunks/{als-slots-mFweg276.js → als-slots-BEEIPKYm.js} +3 -4
- package/dist/_chunks/{als-slots-mFweg276.js.map → als-slots-BEEIPKYm.js.map} +1 -1
- package/dist/_chunks/{cache-api-Cd0VZ_Pd.js → cache-api-DjNrIWRR.js} +7 -13
- package/dist/_chunks/cache-api-DjNrIWRR.js.map +1 -0
- package/dist/_chunks/cli-check-CpmN7Nh-.js +256 -0
- package/dist/_chunks/cli-check-CpmN7Nh-.js.map +1 -0
- package/dist/_chunks/cli-schema-sync-CGMp_Psg.js +298 -0
- package/dist/_chunks/cli-schema-sync-CGMp_Psg.js.map +1 -0
- package/dist/_chunks/{cloudflare-Cs0uZXea.js → cloudflare-CGP6BZKO.js} +4 -3
- package/dist/_chunks/{cloudflare-Cs0uZXea.js.map → cloudflare-CGP6BZKO.js.map} +1 -1
- package/dist/_chunks/convention-lint-kXsgc_-7.js +784 -0
- package/dist/_chunks/convention-lint-kXsgc_-7.js.map +1 -0
- package/dist/_chunks/{error-boundary-DpYRI_I1.js → error-boundary-D-ODYX41.js} +25 -2
- package/dist/_chunks/error-boundary-D-ODYX41.js.map +1 -0
- package/dist/_chunks/file-cache-DmX7OqZP.js +454 -0
- package/dist/_chunks/file-cache-DmX7OqZP.js.map +1 -0
- package/dist/_chunks/{logger-N7e5auP0.js → logger-D8xJZXIN.js} +27 -40
- package/dist/_chunks/logger-D8xJZXIN.js.map +1 -0
- package/dist/_chunks/mdx-file-C005ay-P.js +25 -0
- package/dist/_chunks/mdx-file-C005ay-P.js.map +1 -0
- package/dist/_chunks/{plugin-context-DEGLSJs3.js → plugin-context-rCinWLiE.js} +7 -2
- package/dist/_chunks/{plugin-context-DEGLSJs3.js.map → plugin-context-rCinWLiE.js.map} +1 -1
- package/dist/_chunks/purge-store-Byr8XOjU.js +14 -0
- package/dist/_chunks/purge-store-Byr8XOjU.js.map +1 -0
- package/dist/_chunks/{resolve-schema-Dz3fcFUo.js → resolve-schema-5ma5pp1b.js} +2 -2
- package/dist/_chunks/{resolve-schema-Dz3fcFUo.js.map → resolve-schema-5ma5pp1b.js.map} +1 -1
- package/dist/_chunks/rsc-media-type-DRqE_lD_.js +46 -0
- package/dist/_chunks/rsc-media-type-DRqE_lD_.js.map +1 -0
- package/dist/_chunks/{cli-schema-sync-CKgHC2MB.js → scanner-C8b0Gcw3.js} +5 -298
- package/dist/_chunks/scanner-C8b0Gcw3.js.map +1 -0
- package/dist/_chunks/schema-bridge-Cc2Gngu1.js +199 -0
- package/dist/_chunks/schema-bridge-Cc2Gngu1.js.map +1 -0
- package/dist/_chunks/segment-classify-C539Pa2O.js.map +1 -1
- package/dist/_chunks/{param-value-C8TNYchQ.js → segment-context-CjOlyB8Y.js} +33 -2
- package/dist/_chunks/segment-context-CjOlyB8Y.js.map +1 -0
- package/dist/_chunks/{use-query-states-DFvWd-EA.js → use-query-states-BbU5Ge1V.js} +74 -26
- package/dist/_chunks/use-query-states-BbU5Ge1V.js.map +1 -0
- package/dist/_chunks/{navigation-root-B29qg0_T.js → use-segment-params-C4r4BD9T.js} +129 -5
- package/dist/_chunks/use-segment-params-C4r4BD9T.js.map +1 -0
- package/dist/_chunks/walkers-RzN6AFjr.js +141 -0
- package/dist/_chunks/walkers-RzN6AFjr.js.map +1 -0
- package/dist/adapters/cloudflare-dev.js +1 -1
- package/dist/adapters/cloudflare-kv-cache.js +1 -1
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +1 -1
- package/dist/adapters/compress-module.d.ts +12 -0
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.js +54 -2
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/cache/index.js +1 -1
- package/dist/cdn/cloudflare-purge.js +30 -0
- package/dist/cdn/cloudflare-purge.js.map +1 -0
- package/dist/cdn/fastly-purge.js +33 -0
- package/dist/cdn/fastly-purge.js.map +1 -0
- package/dist/cdn/index.js +94 -0
- package/dist/cdn/index.js.map +1 -0
- package/dist/cdn/workers-cache-purge.js +35 -0
- package/dist/cdn/workers-cache-purge.js.map +1 -0
- package/dist/cli-check.d.ts +153 -0
- package/dist/cli-check.d.ts.map +1 -0
- package/dist/cli.d.ts +34 -8
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +46 -21
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
- package/dist/client/browser-entry/index.d.ts +1 -1
- package/dist/client/browser-entry/index.d.ts.map +1 -1
- package/dist/client/error-boundary.d.ts +6 -0
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +1 -1
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +27 -33
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.js +21 -14
- package/dist/client/internal.js.map +1 -1
- package/dist/client/link.d.ts +1 -7
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/navigation-commit.d.ts +16 -0
- package/dist/client/navigation-commit.d.ts.map +1 -1
- package/dist/client/router-pipeline.d.ts.map +1 -1
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +9 -1
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +8 -0
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/use-query-states.d.ts +9 -3
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/codec.js +1 -1
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.js +2 -2
- package/dist/cookies/index.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +142 -477
- package/dist/index.js.map +1 -1
- package/dist/params/index.js +1 -1
- package/dist/plugin-context.d.ts +15 -0
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/routing.d.ts +0 -9
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +24 -0
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen-shared.d.ts +3 -44
- package/dist/routing/codegen-shared.d.ts.map +1 -1
- package/dist/routing/codegen-types.d.ts +10 -31
- package/dist/routing/codegen-types.d.ts.map +1 -1
- package/dist/routing/codegen-write.d.ts +51 -0
- package/dist/routing/codegen-write.d.ts.map +1 -0
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts +18 -4
- package/dist/routing/convention-lint.d.ts.map +1 -1
- package/dist/routing/export-detect.d.ts +16 -0
- package/dist/routing/export-detect.d.ts.map +1 -1
- package/dist/routing/index.js +3 -2
- package/dist/routing/link-codegen.d.ts +19 -4
- package/dist/routing/link-codegen.d.ts.map +1 -1
- package/dist/routing/manifest-codegen.d.ts +1 -7
- package/dist/routing/manifest-codegen.d.ts.map +1 -1
- package/dist/routing/types.d.ts +0 -6
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +60 -9
- package/dist/schema-bridge.d.ts.map +1 -1
- package/dist/search-params/define.d.ts +62 -8
- package/dist/search-params/define.d.ts.map +1 -1
- package/dist/search-params/index.d.ts +0 -1
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +66 -29
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/parse-total.d.ts +70 -0
- package/dist/search-params/parse-total.d.ts.map +1 -0
- package/dist/search-params/wrappers.d.ts +26 -3
- package/dist/search-params/wrappers.d.ts.map +1 -1
- package/dist/server/access-gate.d.ts +19 -8
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +16 -0
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/compress.d.ts.map +1 -1
- package/dist/server/deny-boundary.d.ts +148 -15
- package/dist/server/deny-boundary.d.ts.map +1 -1
- package/dist/server/deny-renderer.d.ts +2 -2
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +85 -15
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/index.d.ts +0 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +3 -1
- package/dist/server/internal.d.ts.map +1 -1
- package/dist/server/internal.js +343 -230
- package/dist/server/internal.js.map +1 -1
- package/dist/server/metadata-collector.d.ts +52 -0
- package/dist/server/metadata-collector.d.ts.map +1 -0
- package/dist/server/param-coercion.d.ts +12 -5
- package/dist/server/param-coercion.d.ts.map +1 -1
- package/dist/server/pipeline-helpers.d.ts.map +1 -1
- package/dist/server/pipeline-outcome.d.ts.map +1 -1
- package/dist/server/pipeline-phases.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +23 -0
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +1 -12
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/rsc-cache-key-guard.d.ts.map +1 -1
- package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +0 -7
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +0 -1
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +1 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +12 -0
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +0 -2
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +11 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +0 -1
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/static-generator.d.ts.map +1 -1
- package/dist/server/status-code-resolver.d.ts +8 -1
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +28 -36
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +12 -7
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/utils/element-type.d.ts +40 -0
- package/dist/server/utils/element-type.d.ts.map +1 -0
- package/dist/shared/rsc-media-type.d.ts +40 -0
- package/dist/shared/rsc-media-type.d.ts.map +1 -0
- package/docs/api/30-api-server.mdx +1 -1
- package/docs/api/33-api-search-params.mdx +38 -16
- package/docs/api/35-api-typescript.mdx +3 -3
- package/docs/api/36-cli.mdx +34 -7
- package/docs/learn/00-introduction.mdx +1 -1
- package/docs/learn/02-pages-and-layouts.mdx +1 -1
- package/docs/learn/05-typed-params.mdx +8 -8
- package/docs/learn/07-typed-routes.mdx +12 -7
- package/docs/learn/11-error-handling.mdx +16 -0
- package/docs/more/01-advanced-routing.mdx +1 -1
- package/docs/more/03-coming-from-nextjs.mdx +2 -2
- package/docs/more/50-ai-agent-instructions.mdx +6 -4
- package/package.json +8 -5
- package/src/adapters/cloudflare.ts +4 -1
- package/src/adapters/compress-module.ts +79 -1
- package/src/cli-check.ts +458 -0
- package/src/cli.ts +59 -24
- package/src/client/browser-entry/action-dispatch.ts +2 -1
- package/src/client/browser-entry/index.ts +0 -5
- package/src/client/error-boundary.tsx +65 -1
- package/src/client/index.ts +14 -3
- package/src/client/link.tsx +65 -64
- package/src/client/navigation-commit.ts +27 -4
- package/src/client/params-context.ts +4 -4
- package/src/client/router-pipeline.ts +4 -0
- package/src/client/router.ts +1 -0
- package/src/client/rsc-fetch.ts +14 -4
- package/src/client/segment-cache.ts +8 -0
- package/src/client/use-query-states.ts +102 -39
- package/src/cookies/define-cookie.ts +6 -1
- package/src/index.ts +20 -3
- package/src/plugin-context.ts +26 -0
- package/src/plugins/routing.ts +84 -146
- package/src/plugins/shims.ts +0 -1
- package/src/plugins/static-build.ts +78 -24
- package/src/routing/codegen-shared.ts +3 -79
- package/src/routing/codegen-types.ts +10 -31
- package/src/routing/codegen-write.ts +139 -0
- package/src/routing/codegen.ts +56 -182
- package/src/routing/convention-lint.ts +139 -40
- package/src/routing/export-detect.ts +151 -7
- package/src/routing/link-codegen.ts +32 -65
- package/src/routing/manifest-codegen.ts +1 -59
- package/src/routing/scanner.ts +3 -3
- package/src/routing/types.ts +0 -6
- package/src/schema-bridge.ts +180 -58
- package/src/search-params/define.ts +102 -37
- package/src/search-params/index.ts +0 -1
- package/src/search-params/parse-total.ts +78 -0
- package/src/search-params/wrappers.ts +60 -11
- package/src/server/access-gate.tsx +60 -40
- package/src/server/action-handler.ts +1 -4
- package/src/server/als-registry.ts +16 -0
- package/src/server/compress.ts +9 -1
- package/src/server/deny-boundary.ts +269 -41
- package/src/server/deny-renderer.ts +32 -21
- package/src/server/error-boundary-wrapper.ts +166 -79
- package/src/server/index.ts +1 -3
- package/src/server/internal.ts +2 -2
- package/src/server/metadata-collector.ts +115 -0
- package/src/server/param-coercion.ts +13 -61
- package/src/server/pipeline-helpers.ts +2 -2
- package/src/server/pipeline-outcome.ts +2 -1
- package/src/server/pipeline-phases.ts +9 -9
- package/src/server/primitives.ts +25 -0
- package/src/server/route-element-builder.ts +167 -170
- package/src/server/rsc-cache-key-guard.ts +2 -8
- package/src/server/rsc-entry/deny-fallback.ts +3 -2
- package/src/server/rsc-entry/error-renderer.ts +31 -11
- package/src/server/rsc-entry/helpers.ts +2 -12
- package/src/server/rsc-entry/index.ts +0 -5
- package/src/server/rsc-entry/render-route.ts +14 -11
- package/src/server/rsc-entry/revalidate-renderer.ts +2 -1
- package/src/server/rsc-entry/rsc-payload.ts +104 -20
- package/src/server/rsc-entry/rsc-stream.ts +25 -2
- package/src/server/rsc-entry/ssr-renderer.ts +28 -16
- package/src/server/slot-resolver.ts +10 -2
- package/src/server/ssr-bridge-types.ts +12 -0
- package/src/server/ssr-entry.ts +8 -6
- package/src/server/static-generator.ts +3 -2
- package/src/server/status-code-resolver.ts +28 -11
- package/src/server/tree-builder.ts +35 -218
- package/src/server/types.ts +12 -7
- package/src/server/utils/element-type.ts +72 -0
- package/src/shared/rsc-media-type.ts +43 -0
- package/dist/_chunks/cache-api-Cd0VZ_Pd.js.map +0 -1
- package/dist/_chunks/cli-schema-sync-CKgHC2MB.js.map +0 -1
- package/dist/_chunks/error-boundary-DpYRI_I1.js.map +0 -1
- package/dist/_chunks/logger-N7e5auP0.js.map +0 -1
- package/dist/_chunks/navigation-root-B29qg0_T.js.map +0 -1
- package/dist/_chunks/param-value-C8TNYchQ.js.map +0 -1
- package/dist/_chunks/registry-DbJPKoBp.js +0 -20
- package/dist/_chunks/registry-DbJPKoBp.js.map +0 -1
- package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +0 -119
- package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +0 -1
- package/dist/_chunks/segment-context-ZDnXDkbz.js +0 -34
- package/dist/_chunks/segment-context-ZDnXDkbz.js.map +0 -1
- package/dist/_chunks/use-query-states-DFvWd-EA.js.map +0 -1
- package/dist/_chunks/use-segment-params-ClyUNq4d.js +0 -128
- package/dist/_chunks/use-segment-params-ClyUNq4d.js.map +0 -1
- package/dist/_chunks/walkers-BhhwI9TD.js +0 -936
- package/dist/_chunks/walkers-BhhwI9TD.js.map +0 -1
- package/dist/search-params/registry.d.ts +0 -20
- package/dist/search-params/registry.d.ts.map +0 -1
- package/dist/segment-params/define.d.ts +0 -83
- package/dist/segment-params/define.d.ts.map +0 -1
- package/dist/segment-params/index.d.ts +0 -3
- package/dist/segment-params/index.d.ts.map +0 -1
- package/dist/segment-params/index.js +0 -70
- package/dist/segment-params/index.js.map +0 -1
- package/src/search-params/registry.ts +0 -31
- package/src/segment-params/define.ts +0 -226
- package/src/segment-params/index.ts +0 -9
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* defineSegmentParams — factory for typed route param coercion.
|
|
3
|
-
*
|
|
4
|
-
* Creates a ParamsDefinition that coerces raw string params from the
|
|
5
|
-
* URL into typed values. Used by exporting from params.ts (segment-level)
|
|
6
|
-
* convention file.
|
|
7
|
-
*
|
|
8
|
-
* Reuses the shared Codec<T> protocol with Standard Schema auto-detection,
|
|
9
|
-
* same pattern as defineSearchParams. Runtime constraints are stricter:
|
|
10
|
-
* - serialize must return string (not null — path segments can't be omitted)
|
|
11
|
-
* - parse throwing → 404 (invalid param value)
|
|
12
|
-
*
|
|
13
|
-
* Design doc: design/07a-route-params-triage.md
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import type { Codec } from '../codec.js';
|
|
17
|
-
import { type StandardSchemaV1, resolveCodecOrSchema } from '../schema-bridge.js';
|
|
18
|
-
import { useSegmentParams as clientUseSegmentParams } from '../client/use-segment-params.js';
|
|
19
|
-
// Server-only ALS reference for .get(), eagerly registered at server startup
|
|
20
|
-
// from a leaf module so this file stays out of the server graph. Same slot
|
|
21
|
-
// mechanism as search-params. See shared/als-slots.ts, TIM-523, TIM-1298.
|
|
22
|
-
import { getSegmentParamsFromAls } from '../shared/als-slots.js';
|
|
23
|
-
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
// Types
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
|
|
28
|
-
/** Infer the output type from a Codec or StandardSchemaV1. */
|
|
29
|
-
export type InferParamField<V> =
|
|
30
|
-
V extends Codec<infer T> ? T : V extends StandardSchemaV1<infer T> ? T : never;
|
|
31
|
-
|
|
32
|
-
/** Acceptable field value for defineParams: a Codec or a Standard Schema. */
|
|
33
|
-
export type ParamField<T = unknown> = Codec<T> | StandardSchemaV1<T>;
|
|
34
|
-
|
|
35
|
-
export type { StandardSchemaV1 };
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* A typed route params definition.
|
|
39
|
-
*
|
|
40
|
-
* Returned by defineParams(). Provides parse (string → typed) and
|
|
41
|
-
* serialize (typed → string) for each declared param.
|
|
42
|
-
*/
|
|
43
|
-
export interface ParamsDefinition<T extends Record<string, unknown>> {
|
|
44
|
-
/** Parse raw string params into typed values. Throws on invalid values. */
|
|
45
|
-
parse(raw: Record<string, string | string[]>): T;
|
|
46
|
-
|
|
47
|
-
/** Serialize typed values back to strings for URL construction. */
|
|
48
|
-
serialize(values: T): Record<string, string>;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Get typed segment params from the current request context (ALS).
|
|
52
|
-
*
|
|
53
|
-
* Server-only, sync.
|
|
54
|
-
*
|
|
55
|
-
* ```ts
|
|
56
|
-
* // app/products/[id]/params.ts
|
|
57
|
-
* export const segmentParams = defineSegmentParams({ id: z.coerce.number() })
|
|
58
|
-
*
|
|
59
|
-
* // app/products/[id]/page.tsx
|
|
60
|
-
* import { segmentParams } from './params'
|
|
61
|
-
* export default function Page() {
|
|
62
|
-
* const { id } = segmentParams.get() // id: number
|
|
63
|
-
* }
|
|
64
|
-
* ```
|
|
65
|
-
*/
|
|
66
|
-
get(): T;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Client hook for accessing typed segment params reactively.
|
|
70
|
-
*
|
|
71
|
-
* ```tsx
|
|
72
|
-
* 'use client'
|
|
73
|
-
* import { segmentParams } from './params'
|
|
74
|
-
* export function ProductHeader() {
|
|
75
|
-
* const { id } = segmentParams.useSegmentParams()
|
|
76
|
-
* }
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
useSegmentParams(): T;
|
|
80
|
-
|
|
81
|
-
/** Read-only codec map. */
|
|
82
|
-
codecs: { [K in keyof T]: Codec<T[K]> };
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// ---------------------------------------------------------------------------
|
|
86
|
-
// Internal helpers
|
|
87
|
-
// ---------------------------------------------------------------------------
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Validate that no codec's serialize returns null.
|
|
91
|
-
* Route params are structural — they must produce a valid path segment.
|
|
92
|
-
*/
|
|
93
|
-
function validateSerialize(codecMap: Record<string, Codec<unknown>>): void {
|
|
94
|
-
for (const [key, codec] of Object.entries(codecMap)) {
|
|
95
|
-
// Test serialize with a sample parsed value to check for null
|
|
96
|
-
// We can't exhaustively test, but we can check that serialize(parse("test"))
|
|
97
|
-
// doesn't return null for a basic input.
|
|
98
|
-
try {
|
|
99
|
-
const testValue = codec.parse('test');
|
|
100
|
-
const serialized = codec.serialize(testValue);
|
|
101
|
-
if (serialized === null) {
|
|
102
|
-
throw new Error(
|
|
103
|
-
`[timber] defineSegmentParams: field '${key}' codec.serialize() returned null.\n` +
|
|
104
|
-
` Route params are path segments — they cannot be omitted.\n` +
|
|
105
|
-
` Ensure serialize() always returns a string.`
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
} catch (e) {
|
|
109
|
-
// parse('test') may throw for strict codecs (e.g., number-only).
|
|
110
|
-
// That's fine — it means the codec validates. We only care about
|
|
111
|
-
// serialize returning null, which we can't test without a valid value.
|
|
112
|
-
if (e instanceof Error && e.message.includes('returned null')) {
|
|
113
|
-
throw e;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// ---------------------------------------------------------------------------
|
|
120
|
-
// Factory
|
|
121
|
-
// ---------------------------------------------------------------------------
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Create a ParamsDefinition from a map of codecs and/or Standard Schema objects.
|
|
125
|
-
*
|
|
126
|
-
* ```ts
|
|
127
|
-
* // app/products/[id]/layout.tsx
|
|
128
|
-
* import { defineSegmentParams } from '@timber-js/app/segment-params'
|
|
129
|
-
* import { z } from 'zod/v4'
|
|
130
|
-
*
|
|
131
|
-
* export const segmentParams = defineSegmentParams({
|
|
132
|
-
* id: z.coerce.number().int().positive(),
|
|
133
|
-
* })
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
export function defineSegmentParams<C extends Record<string, ParamField>>(
|
|
137
|
-
codecs: C
|
|
138
|
-
): ParamsDefinition<{ [K in keyof C]: InferParamField<C[K]> }> {
|
|
139
|
-
type T = { [K in keyof C]: InferParamField<C[K]> };
|
|
140
|
-
|
|
141
|
-
const resolvedCodecs: Record<string, Codec<unknown>> = {};
|
|
142
|
-
|
|
143
|
-
for (const [key, value] of Object.entries(codecs)) {
|
|
144
|
-
resolvedCodecs[key] = resolveCodecOrSchema(key, value, 'param');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Validate that serialize doesn't return null
|
|
148
|
-
validateSerialize(resolvedCodecs);
|
|
149
|
-
|
|
150
|
-
// ---- parse ----
|
|
151
|
-
function parse(raw: Record<string, string | string[]>): T {
|
|
152
|
-
const result: Record<string, unknown> = {};
|
|
153
|
-
|
|
154
|
-
for (const [key, codec] of Object.entries(resolvedCodecs)) {
|
|
155
|
-
const rawValue = raw[key];
|
|
156
|
-
// Skip params not present in the URL at this route depth.
|
|
157
|
-
// This supports TIM-834 inheritance: a parent params.ts can declare
|
|
158
|
-
// codecs for descendant segments. At shallower depths those params
|
|
159
|
-
// don't exist yet — skip them instead of passing undefined to the codec.
|
|
160
|
-
if (rawValue === undefined) continue;
|
|
161
|
-
result[key] = codec.parse(rawValue);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return result as T;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// ---- serialize ----
|
|
168
|
-
function serialize(values: T): Record<string, string> {
|
|
169
|
-
const result: Record<string, string> = {};
|
|
170
|
-
|
|
171
|
-
for (const [key, codec] of Object.entries(resolvedCodecs)) {
|
|
172
|
-
const serialized = codec.serialize(values[key as keyof T] as unknown);
|
|
173
|
-
if (serialized === null) {
|
|
174
|
-
throw new Error(
|
|
175
|
-
`[timber] params.serialize: field '${key}' serialized to null. ` +
|
|
176
|
-
`Route params must produce a valid path segment.`
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
result[key] = serialized;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return result;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// ---- get ----
|
|
186
|
-
// ALS-backed: reads segment params from the current request context.
|
|
187
|
-
// Server-only, sync.
|
|
188
|
-
//
|
|
189
|
-
// The pipeline already coerces params via coerceSegmentParams() which
|
|
190
|
-
// calls parse() and stores typed values in ALS via setSegmentParams().
|
|
191
|
-
// We return those directly instead of re-parsing, because codecs may
|
|
192
|
-
// not be idempotent (e.g., a codec that only accepts raw strings would
|
|
193
|
-
// throw if given an already-parsed value). See TIM-574.
|
|
194
|
-
function get(): T {
|
|
195
|
-
if (typeof window !== 'undefined') {
|
|
196
|
-
throw new Error(
|
|
197
|
-
'[timber] segmentParams.get() is server-only. ' +
|
|
198
|
-
'Use segmentParams.useSegmentParams() on the client.'
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
const params = getSegmentParamsFromAls();
|
|
202
|
-
// params are already coerced by the pipeline — return as-is.
|
|
203
|
-
return params as unknown as T;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// ---- useSegmentParams ----
|
|
207
|
-
// Client hook that reads typed params from the navigation context.
|
|
208
|
-
// Delegates to the existing useSegmentParams hook from use-segment-params.ts.
|
|
209
|
-
function useSegmentParams(): T {
|
|
210
|
-
const raw = clientUseSegmentParams();
|
|
211
|
-
// Params are already coerced by the server pipeline before being sent
|
|
212
|
-
// to the client — return as-is. Re-parsing would break non-idempotent
|
|
213
|
-
// codecs (e.g., z.coerce.number() on an already-parsed number). See TIM-574.
|
|
214
|
-
return raw as unknown as T;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const definition: ParamsDefinition<T> = {
|
|
218
|
-
parse,
|
|
219
|
-
serialize,
|
|
220
|
-
get,
|
|
221
|
-
useSegmentParams,
|
|
222
|
-
codecs: resolvedCodecs as { [K in keyof T]: Codec<T[K]> },
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
return definition;
|
|
226
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// @timber-js/app/segment-params — Typed route param coercion
|
|
2
|
-
//
|
|
3
|
-
// This is the import path for defineSegmentParams and related types.
|
|
4
|
-
// For search params, import from @timber-js/app/search-params instead.
|
|
5
|
-
//
|
|
6
|
-
// See design/07-routing.md §"params.ts Convention File"
|
|
7
|
-
|
|
8
|
-
export type { ParamsDefinition, InferParamField, ParamField } from './define.js';
|
|
9
|
-
export { defineSegmentParams } from './define.js';
|