@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
|
@@ -20,7 +20,13 @@ interface AstNode {
|
|
|
20
20
|
exportKind?: string;
|
|
21
21
|
}>;
|
|
22
22
|
id?: { name: string };
|
|
23
|
-
declarations?: Array<{ id?: { name: string } }>;
|
|
23
|
+
declarations?: Array<{ id?: { name: string }; init?: AstNode }>;
|
|
24
|
+
/** Set on re-exports: `export { X } from './y'`. Absent on local exports. */
|
|
25
|
+
source?: { value?: string } | null;
|
|
26
|
+
/** Set on runtime-transparent wrappers: `X as T`, `X satisfies T`, `(X)`, `X!`. */
|
|
27
|
+
expression?: AstNode;
|
|
28
|
+
/** Set on `Identifier` nodes. */
|
|
29
|
+
name?: string;
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
interface ProgramNode {
|
|
@@ -71,19 +77,41 @@ function collectNamedExports(program: ProgramNode): Set<string> {
|
|
|
71
77
|
return names;
|
|
72
78
|
}
|
|
73
79
|
|
|
80
|
+
/**
|
|
81
|
+
* The specifier exporting a *runtime* default from this statement, if any.
|
|
82
|
+
*
|
|
83
|
+
* Type-only exports erase, so they are not default exports at runtime — and
|
|
84
|
+
* TypeScript spells that two ways, on two different nodes: `export type { X as
|
|
85
|
+
* default }` marks the **statement**, `export { type X as default }` marks the
|
|
86
|
+
* **specifier**. Both have to be checked, or a type alias reads as a component:
|
|
87
|
+
* a status file whose only default is a type has nothing for the error boundary
|
|
88
|
+
* to receive (the renderer's `mod?.default` skips it), so treating it as one
|
|
89
|
+
* would fail a build over a file that cannot break anything.
|
|
90
|
+
*
|
|
91
|
+
* One implementation because two callers must agree on what "has a default
|
|
92
|
+
* export" means: `hasDefaultExport` decides whether to warn that a page has
|
|
93
|
+
* none, and `fileDefaultExportIsLocalValue` decides whether to fail the build.
|
|
94
|
+
*/
|
|
95
|
+
function defaultSpecifier(stmt: AstNode): NonNullable<AstNode['specifiers']>[number] | null {
|
|
96
|
+
if (stmt.type !== 'ExportNamedDeclaration' || !stmt.specifiers) return null;
|
|
97
|
+
if (stmt.exportKind === 'type') return null;
|
|
98
|
+
for (const spec of stmt.specifiers) {
|
|
99
|
+
if (spec.exportKind === 'type') continue;
|
|
100
|
+
if (spec.exported?.name === 'default') return spec;
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
74
105
|
/**
|
|
75
106
|
* Check whether a program has a default export.
|
|
76
107
|
* Handles: `export default ...`, `export { X as default }`,
|
|
77
|
-
* `export { default } from '...'`.
|
|
108
|
+
* `export { default } from '...'`. Type-only defaults do not count —
|
|
109
|
+
* see `defaultSpecifier`.
|
|
78
110
|
*/
|
|
79
111
|
function hasDefaultExport(program: ProgramNode): boolean {
|
|
80
112
|
for (const stmt of program.body) {
|
|
81
113
|
if (stmt.type === 'ExportDefaultDeclaration') return true;
|
|
82
|
-
if (stmt
|
|
83
|
-
for (const spec of stmt.specifiers) {
|
|
84
|
-
if (spec.exported?.name === 'default') return true;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
114
|
+
if (defaultSpecifier(stmt)) return true;
|
|
87
115
|
}
|
|
88
116
|
return false;
|
|
89
117
|
}
|
|
@@ -152,6 +180,122 @@ export function fileHasDefaultExport(filePath: string): boolean {
|
|
|
152
180
|
}
|
|
153
181
|
}
|
|
154
182
|
|
|
183
|
+
/** Node types whose value is unambiguously constructed by this module. */
|
|
184
|
+
const FUNCTION_LIKE = new Set([
|
|
185
|
+
'FunctionDeclaration',
|
|
186
|
+
'FunctionExpression',
|
|
187
|
+
'ArrowFunctionExpression',
|
|
188
|
+
'ClassDeclaration',
|
|
189
|
+
'ClassExpression',
|
|
190
|
+
]);
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Expression wrappers that erase at runtime and so cannot change where a value
|
|
194
|
+
* was constructed: `X as T`, `X satisfies T`, `<T>X`, `X!`, `X<T>`, `(X)`.
|
|
195
|
+
*/
|
|
196
|
+
const TRANSPARENT_WRAPPERS = new Set([
|
|
197
|
+
'TSAsExpression',
|
|
198
|
+
'TSSatisfiesExpression',
|
|
199
|
+
'TSTypeAssertion',
|
|
200
|
+
'TSNonNullExpression',
|
|
201
|
+
'TSInstantiationExpression',
|
|
202
|
+
'ParenthesizedExpression',
|
|
203
|
+
]);
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Strip runtime-transparent wrappers so the node underneath can be classified.
|
|
207
|
+
*
|
|
208
|
+
* Without this, `(() => <h1 />) satisfies React.FC` reads as a
|
|
209
|
+
* `TSSatisfiesExpression` rather than the arrow function it compiles to, and a
|
|
210
|
+
* provably-local component is misread as one whose origin cannot be
|
|
211
|
+
* determined — turning a build error into a warning.
|
|
212
|
+
*/
|
|
213
|
+
function unwrapTransparent(node: AstNode): AstNode {
|
|
214
|
+
let current = node;
|
|
215
|
+
while (TRANSPARENT_WRAPPERS.has(current.type) && current.expression) {
|
|
216
|
+
current = current.expression;
|
|
217
|
+
}
|
|
218
|
+
return current;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Whether `name` is bound at module top level to a function or class written
|
|
223
|
+
* in this file. An imported binding can never match: imports are
|
|
224
|
+
* `ImportDeclaration` specifiers, not function/class/variable declarations,
|
|
225
|
+
* and a module-level name cannot be both.
|
|
226
|
+
*/
|
|
227
|
+
function bindsLocalFunction(program: ProgramNode, name: string): boolean {
|
|
228
|
+
for (const stmt of program.body) {
|
|
229
|
+
// `export function X() {}` binds X locally too — unwrap the export.
|
|
230
|
+
const decl = stmt.type === 'ExportNamedDeclaration' ? stmt.declaration : stmt;
|
|
231
|
+
if (!decl) continue;
|
|
232
|
+
if (
|
|
233
|
+
(decl.type === 'FunctionDeclaration' || decl.type === 'ClassDeclaration') &&
|
|
234
|
+
decl.id?.name === name
|
|
235
|
+
) {
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
if (decl.type === 'VariableDeclaration') {
|
|
239
|
+
for (const d of decl.declarations ?? []) {
|
|
240
|
+
if (d.id?.name === name && d.init && FUNCTION_LIKE.has(unwrapTransparent(d.init).type)) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Whether the default export is *provably* a value constructed by this module:
|
|
251
|
+
* `export default function/class/() => {}`, or a name bound to a function or
|
|
252
|
+
* class declared here — whether it leaves via `export default Name` or
|
|
253
|
+
* `export { Name as default }`. Both spellings are the same fact about where
|
|
254
|
+
* the value was built, so both must answer the same way.
|
|
255
|
+
*
|
|
256
|
+
* This is the sound half of "is this a server component?". A file with no
|
|
257
|
+
* `'use client'` directive whose default export is built here is a server
|
|
258
|
+
* component, full stop. Everything else — `export { default } from
|
|
259
|
+
* './client-thing'`, `export default Imported`, `export default memo(X)`,
|
|
260
|
+
* an unparseable file — returns false, because the exported value may have
|
|
261
|
+
* been minted in a module that *does* carry the directive. Callers must not
|
|
262
|
+
* infer "server component" from a missing directive alone.
|
|
263
|
+
*/
|
|
264
|
+
export function fileDefaultExportIsLocalValue(filePath: string): boolean {
|
|
265
|
+
if (!existsSync(filePath)) return false;
|
|
266
|
+
try {
|
|
267
|
+
const source = readFileCached(filePath);
|
|
268
|
+
const program = tryParse(source);
|
|
269
|
+
if (!program) return false;
|
|
270
|
+
for (const stmt of program.body) {
|
|
271
|
+
if (stmt.type === 'ExportDefaultDeclaration') {
|
|
272
|
+
const decl = stmt.declaration && unwrapTransparent(stmt.declaration);
|
|
273
|
+
if (!decl) return false;
|
|
274
|
+
if (FUNCTION_LIKE.has(decl.type)) return true;
|
|
275
|
+
if (decl.type === 'Identifier' && decl.name) {
|
|
276
|
+
return bindsLocalFunction(program, decl.name);
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// `export { Name as default }` — the same default export by another
|
|
282
|
+
// spelling. `hasDefaultExport` already counts it, so an analysis that
|
|
283
|
+
// skipped it here would let the exact defect this powers slip through
|
|
284
|
+
// as a warning.
|
|
285
|
+
const spec = defaultSpecifier(stmt);
|
|
286
|
+
if (spec) {
|
|
287
|
+
// `export { X as default } from './client-thing'` re-exports another
|
|
288
|
+
// module's value — the directive governing it lives over there.
|
|
289
|
+
if (stmt.source) return false;
|
|
290
|
+
return spec.local?.name ? bindsLocalFunction(program, spec.local.name) : false;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return false;
|
|
294
|
+
} catch {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
155
299
|
/**
|
|
156
300
|
* Check if a file has any `export * from '...'` declarations.
|
|
157
301
|
* Returns false if the file doesn't exist or can't be parsed.
|
|
@@ -24,13 +24,24 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import type { ParamEntry, RouteEntry } from './codegen-types.js';
|
|
27
|
-
import {
|
|
28
|
-
buildCodecChainType,
|
|
29
|
-
buildSchemaParamType,
|
|
30
|
-
formatSearchParamsType,
|
|
31
|
-
} from './codegen-shared.js';
|
|
27
|
+
import { buildSchemaParamType } from './codegen-shared.js';
|
|
32
28
|
import { classifyUrlSegment } from './segment-classify.js';
|
|
33
29
|
|
|
30
|
+
/**
|
|
31
|
+
* The `searchParams` prop type, emitted identically on every Link variant
|
|
32
|
+
* — per-route pattern, resolved template, and catch-all.
|
|
33
|
+
*
|
|
34
|
+
* TIM-1343: there is no per-route narrowing any more. `params.ts` is gone,
|
|
35
|
+
* so codegen has no definition to read a `SearchParamsDefinition<T>` from.
|
|
36
|
+
* Type safety moved to the value's construction site instead: callers write
|
|
37
|
+
* `definition.buildSearchParams({ ... })`, which checks `Partial<T>` there
|
|
38
|
+
* and returns a query STRING — the only shape that survives the RSC Flight
|
|
39
|
+
* boundary. A plain record is the uncodec'd escape hatch. See `client/link.tsx` §"searchParams prop shapes".
|
|
40
|
+
*
|
|
41
|
+
* Declared once so the three emission sites cannot drift apart.
|
|
42
|
+
*/
|
|
43
|
+
export const SEARCH_PARAMS_PROP_TYPE = 'string | Record<string, unknown>';
|
|
44
|
+
|
|
34
45
|
/** Shared Link base-props type literal used in every emitted call signature. */
|
|
35
46
|
export const LINK_BASE_PROPS_TYPE =
|
|
36
47
|
"Omit<import('react').AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> & { prefetch?: boolean; scroll?: boolean; preserveSearchParams?: true | string[]; onNavigate?: import('./client/link.js').OnNavigateHandler; children?: import('react').ReactNode }";
|
|
@@ -71,23 +82,18 @@ export function buildResolvedPattern(route: RouteEntry): string | null {
|
|
|
71
82
|
* (convenience — values are stringified at runtime). Catch-all and
|
|
72
83
|
* optional catch-all remain `string[]` / `string[] | undefined`.
|
|
73
84
|
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
85
|
+
* With a global schema, the schema codec's inferred type wins. Without
|
|
86
|
+
* one, a URL segment is a raw string (widened to string | number for
|
|
87
|
+
* Link convenience) — per-segment codec chains were deleted in TIM-1342.
|
|
76
88
|
*/
|
|
77
|
-
export function formatLinkParamsType(
|
|
78
|
-
params: ParamEntry[],
|
|
79
|
-
importBase?: string,
|
|
80
|
-
hasSchema?: boolean
|
|
81
|
-
): string {
|
|
89
|
+
export function formatLinkParamsType(params: ParamEntry[], hasSchema?: boolean): string {
|
|
82
90
|
if (params.length === 0) {
|
|
83
91
|
return '{}';
|
|
84
92
|
}
|
|
85
93
|
|
|
86
94
|
const fields = params.map((p) => {
|
|
87
95
|
const fallback = p.type === 'string' ? 'string | number' : p.type;
|
|
88
|
-
const codecType = hasSchema
|
|
89
|
-
? buildSchemaParamType(p, fallback)
|
|
90
|
-
: buildCodecChainType(p, importBase, fallback);
|
|
96
|
+
const codecType = hasSchema ? buildSchemaParamType(p, fallback) : fallback;
|
|
91
97
|
return `${p.name}: ${codecType}`;
|
|
92
98
|
});
|
|
93
99
|
return `{ ${fields.join('; ')} }`;
|
|
@@ -109,15 +115,7 @@ export function formatLinkCatchAllOverloads(): string[] {
|
|
|
109
115
|
const lines: string[] = [];
|
|
110
116
|
const baseProps = LINK_BASE_PROPS_TYPE;
|
|
111
117
|
|
|
112
|
-
|
|
113
|
-
// `{ definition, values }` wrapper OR a flat `Record<string, unknown>`
|
|
114
|
-
// values object. External/computed hrefs can't be looked up in the
|
|
115
|
-
// runtime registry, so the wrapped form is still the reliable path;
|
|
116
|
-
// the flat form is kept permissive for callers migrating from typed-
|
|
117
|
-
// route hrefs to computed strings. `resolveHref` discriminates at
|
|
118
|
-
// runtime via the presence of a `definition` key.
|
|
119
|
-
const catchAllSearchParams =
|
|
120
|
-
'{ definition: SearchParamsDefinition<Record<string, unknown>>; values: Record<string, unknown> } | Record<string, unknown>';
|
|
118
|
+
const catchAllSearchParams = SEARCH_PARAMS_PROP_TYPE;
|
|
121
119
|
|
|
122
120
|
// ExternalHref inlined here rather than referenced as an exported
|
|
123
121
|
// alias so the generated .d.ts stands alone without source imports.
|
|
@@ -207,11 +205,7 @@ export function formatLinkCatchAllOverloads(): string[] {
|
|
|
207
205
|
* so the resolved-template-vs-pattern ordering reduces to placing the
|
|
208
206
|
* pattern variant before the resolved-template variant inside the union.
|
|
209
207
|
*/
|
|
210
|
-
export function formatTypedLinkOverloads(
|
|
211
|
-
routes: RouteEntry[],
|
|
212
|
-
importBase?: string,
|
|
213
|
-
hasSchema?: boolean
|
|
214
|
-
): string[] {
|
|
208
|
+
export function formatTypedLinkOverloads(routes: RouteEntry[], hasSchema?: boolean): string[] {
|
|
215
209
|
const lines: string[] = [];
|
|
216
210
|
const baseProps = LINK_BASE_PROPS_TYPE;
|
|
217
211
|
|
|
@@ -234,52 +228,25 @@ export function formatTypedLinkOverloads(
|
|
|
234
228
|
// segmentParams. `Record<string, unknown>` keeps generic spreads
|
|
235
229
|
// compiling and gives a readable error if a non-object is passed.
|
|
236
230
|
const paramsProp = hasDynamicParams
|
|
237
|
-
? `segmentParams: ${formatLinkParamsType(route.params,
|
|
231
|
+
? `segmentParams: ${formatLinkParamsType(route.params, hasSchema)}`
|
|
238
232
|
: 'segmentParams?: Record<string, unknown>';
|
|
239
233
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
// TIM-833: when the route has NO searchParams definition, use
|
|
247
|
-
// `Record<string, unknown>` (open shape) instead of
|
|
248
|
-
// `Record<string, never>` so generic `LinkProps`-spreading wrappers
|
|
249
|
-
// compile. The trade-off vs the original TIM-835 strict shape is
|
|
250
|
-
// that excess searchParams keys on a no-def route no longer raise
|
|
251
|
-
// a type error — but those keys are runtime no-ops anyway, and
|
|
252
|
-
// wrapper compatibility is the more common pain point. Routes WITH
|
|
253
|
-
// a searchParams definition still get strict `Partial<T>` typing.
|
|
254
|
-
const patternSearchParamsProp = searchParamsType
|
|
255
|
-
? `searchParams?: Partial<${searchParamsType}>`
|
|
256
|
-
: 'searchParams?: Record<string, unknown>';
|
|
234
|
+
// TIM-1343: searchParams is no longer typed per-route. There is no
|
|
235
|
+
// convention file to read a definition from, so codegen has nothing to
|
|
236
|
+
// narrow with — the value is either a URLSearchParams built by
|
|
237
|
+
// `definition.buildSearchParams()` (which type-checks its own
|
|
238
|
+
// `Partial<T>` at that call) or a plain String()-coerced record.
|
|
239
|
+
const searchParamsProp = `searchParams?: ${SEARCH_PARAMS_PROP_TYPE}`;
|
|
257
240
|
|
|
258
241
|
// Pattern variant FIRST (more specific).
|
|
259
242
|
variants.push(
|
|
260
|
-
`${baseProps} & { href: '${route.urlPath}'; ${paramsProp}; ${
|
|
243
|
+
`${baseProps} & { href: '${route.urlPath}'; ${paramsProp}; ${searchParamsProp} }`
|
|
261
244
|
);
|
|
262
245
|
|
|
263
246
|
// Resolved-template variant SECOND (looser, matches interpolated hrefs).
|
|
264
247
|
if (hasDynamicParams) {
|
|
265
248
|
const templatePattern = buildResolvedPattern(route);
|
|
266
249
|
if (templatePattern) {
|
|
267
|
-
// TIM-830: resolved-template href keeps the WRAPPED
|
|
268
|
-
// `{ definition, values }` shape — the registry can't be looked
|
|
269
|
-
// up by an already-interpolated href.
|
|
270
|
-
//
|
|
271
|
-
// TIM-833: searchParams falls back to `Record<string, unknown>`
|
|
272
|
-
// (was `Record<string, never>`) when the route has no
|
|
273
|
-
// definition, mirroring the pattern-variant change above. The
|
|
274
|
-
// resolved-template `segmentParams` is intentionally KEPT as
|
|
275
|
-
// `Record<string, never>` below to preserve TIM-835's
|
|
276
|
-
// pattern-variant typo detection: loosening segmentParams here
|
|
277
|
-
// would let the resolved-template variant shadow the pattern
|
|
278
|
-
// variant on literal pattern hrefs and silently swallow keyed
|
|
279
|
-
// typos like `<Link href="/[id]" segmentParams={{ idz: 1 }} />`.
|
|
280
|
-
const resolvedSearchParamsProp = searchParamsType
|
|
281
|
-
? `searchParams?: { definition: SearchParamsDefinition<${searchParamsType}>; values: Partial<${searchParamsType}> }`
|
|
282
|
-
: 'searchParams?: Record<string, unknown>';
|
|
283
250
|
// TIM-835: `Record<string, never>` for segmentParams forbids ANY
|
|
284
251
|
// provided keys on the resolved-template variant. Without this,
|
|
285
252
|
// the resolved-template would shadow the pattern variant for
|
|
@@ -288,7 +255,7 @@ export function formatTypedLinkOverloads(
|
|
|
288
255
|
// and the looser variant would silently swallow segmentParams
|
|
289
256
|
// type errors.
|
|
290
257
|
variants.push(
|
|
291
|
-
`${baseProps} & { href: \`${templatePattern}\`; segmentParams?: Record<string, never>; ${
|
|
258
|
+
`${baseProps} & { href: \`${templatePattern}\`; segmentParams?: Record<string, never>; ${searchParamsProp} }`
|
|
292
259
|
);
|
|
293
260
|
}
|
|
294
261
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Route manifest codegen — generates virtual module source for the route
|
|
3
|
-
* manifest
|
|
3
|
+
* manifest and the global schema loader.
|
|
4
4
|
*
|
|
5
5
|
* Extracted from plugins/routing.ts to keep it under the 500-line budget.
|
|
6
6
|
* See design/18-build-system.md §"Virtual Modules".
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
import { existsSync } from 'node:fs';
|
|
12
12
|
import { join } from 'node:path';
|
|
13
13
|
import { collectInterceptionRewrites } from './interception.js';
|
|
14
|
-
import { fileHasExport } from './export-detect.js';
|
|
15
14
|
import type { RouteTree, SegmentNode, RouteFile } from './types.js';
|
|
16
15
|
|
|
17
16
|
// ── Single-file conventions ─────────────────────────────────────────────
|
|
@@ -26,7 +25,6 @@ const SINGLE_FILE_KEYS = [
|
|
|
26
25
|
'error',
|
|
27
26
|
'default',
|
|
28
27
|
'denied',
|
|
29
|
-
'params',
|
|
30
28
|
] as const;
|
|
31
29
|
|
|
32
30
|
// ── Record-shaped conventions ───────────────────────────────────────────
|
|
@@ -107,10 +105,6 @@ export function generateManifestModule(tree: RouteTree, viteRoot: string): strin
|
|
|
107
105
|
}
|
|
108
106
|
}
|
|
109
107
|
|
|
110
|
-
// searchParams is now a named export from page.tsx, not a separate file.
|
|
111
|
-
// The page module's searchParams export is loaded via the page's lazy import.
|
|
112
|
-
// Runtime registration happens in the route loader using the page module.
|
|
113
|
-
|
|
114
108
|
// Record-shaped conventions — table-driven
|
|
115
109
|
for (const key of RECORD_FILE_KEYS) {
|
|
116
110
|
const record = node[key];
|
|
@@ -190,58 +184,6 @@ export function generateManifestModule(tree: RouteTree, viteRoot: string): strin
|
|
|
190
184
|
return code;
|
|
191
185
|
}
|
|
192
186
|
|
|
193
|
-
// ── Search-params registry ──────────────────────────────────────────────
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Walk the route tree and collect every page that exports a
|
|
197
|
-
* `searchParams` definition, then emit a module that statically imports
|
|
198
|
-
* each export and registers it into the shared search-params registry.
|
|
199
|
-
*/
|
|
200
|
-
export function generateSearchParamsRegistryModule(tree: RouteTree): string {
|
|
201
|
-
const entries: Array<{ urlPath: string; filePath: string }> = [];
|
|
202
|
-
|
|
203
|
-
function walk(node: SegmentNode): void {
|
|
204
|
-
if (node.page) {
|
|
205
|
-
if (node.params && fileHasSearchParamsExport(node.params.filePath)) {
|
|
206
|
-
entries.push({ urlPath: node.urlPath, filePath: node.params.filePath });
|
|
207
|
-
} else if (fileHasSearchParamsExport(node.page.filePath)) {
|
|
208
|
-
entries.push({ urlPath: node.urlPath, filePath: node.page.filePath });
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
for (const child of node.children) walk(child);
|
|
212
|
-
for (const slot of Object.values(node.slots)) walk(slot);
|
|
213
|
-
}
|
|
214
|
-
walk(tree.root);
|
|
215
|
-
|
|
216
|
-
entries.sort((a, b) => a.urlPath.localeCompare(b.urlPath));
|
|
217
|
-
|
|
218
|
-
const lines: string[] = [];
|
|
219
|
-
lines.push('// Auto-generated search-params registry — do not edit.');
|
|
220
|
-
lines.push('// Generated by timber-routing plugin (TIM-830).');
|
|
221
|
-
lines.push('');
|
|
222
|
-
lines.push("import { registerSearchParams } from '@timber-js/app/search-params';");
|
|
223
|
-
lines.push('');
|
|
224
|
-
|
|
225
|
-
entries.forEach((entry, i) => {
|
|
226
|
-
lines.push(`import { searchParams as r${i} } from ${JSON.stringify(entry.filePath)};`);
|
|
227
|
-
});
|
|
228
|
-
lines.push('');
|
|
229
|
-
|
|
230
|
-
entries.forEach((entry, i) => {
|
|
231
|
-
lines.push(`registerSearchParams(${JSON.stringify(entry.urlPath)}, r${i});`);
|
|
232
|
-
});
|
|
233
|
-
lines.push('');
|
|
234
|
-
|
|
235
|
-
lines.push('export {};');
|
|
236
|
-
lines.push('');
|
|
237
|
-
|
|
238
|
-
return lines.join('\n');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function fileHasSearchParamsExport(filePath: string): boolean {
|
|
242
|
-
return fileHasExport(filePath, 'searchParams');
|
|
243
|
-
}
|
|
244
|
-
|
|
245
187
|
// ── Schema module ───────────────────────────────────────────────────────
|
|
246
188
|
|
|
247
189
|
/**
|
package/src/routing/scanner.ts
CHANGED
|
@@ -35,7 +35,7 @@ const PAGE_EXT_CONVENTIONS = new Set(['page', 'layout', 'error', 'default', 'den
|
|
|
35
35
|
/**
|
|
36
36
|
* File convention names that are always .ts/.tsx (never .mdx etc.)
|
|
37
37
|
*/
|
|
38
|
-
const FIXED_CONVENTIONS = new Set(['middleware', 'access', 'route'
|
|
38
|
+
const FIXED_CONVENTIONS = new Set(['middleware', 'access', 'route']);
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Status-code file patterns:
|
|
@@ -184,12 +184,12 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
|
|
|
184
184
|
continue;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
// Fixed conventions (middleware, access, route
|
|
187
|
+
// Fixed conventions (middleware, access, route) — only
|
|
188
188
|
// .ts/.tsx/.js/.jsx, never pageExtensions like .mdx. The regex is
|
|
189
189
|
// anchored: mts/cts/mjs/cjs (and stray tail matches like `.foots`)
|
|
190
190
|
// are NOT recognized. See design/07-routing.md §"Page Extensions".
|
|
191
191
|
if (FIXED_CONVENTIONS.has(name) && /^[jt]sx?$/.test(ext)) {
|
|
192
|
-
const key = name as 'middleware' | 'access' | 'route'
|
|
192
|
+
const key = name as 'middleware' | 'access' | 'route';
|
|
193
193
|
const existing = node[key];
|
|
194
194
|
if (existing) {
|
|
195
195
|
throwDuplicateConvention(name, existing.filePath, fullPath);
|
package/src/routing/types.ts
CHANGED
|
@@ -96,12 +96,6 @@ export interface SegmentNode<TFile = RouteFile> {
|
|
|
96
96
|
middleware?: TFile;
|
|
97
97
|
access?: TFile;
|
|
98
98
|
route?: TFile;
|
|
99
|
-
/**
|
|
100
|
-
* params.ts — isomorphic convention file exporting segmentParams and/or searchParams.
|
|
101
|
-
* Discovered by the scanner like middleware.ts and access.ts.
|
|
102
|
-
* See design/07-routing.md §"params.ts Convention File"
|
|
103
|
-
*/
|
|
104
|
-
params?: TFile;
|
|
105
99
|
error?: TFile;
|
|
106
100
|
default?: TFile;
|
|
107
101
|
/** Status-code files: 4xx.tsx, 5xx.tsx, {status}.tsx (component format) */
|