Skip to content

Commit 1cd93cd

Browse files
dummdidummRich-HarrisConduitry
authored
fix: ignore route groups when generating typed routes (#14050)
Fixes #14043 Fixes #14044 --------- Co-authored-by: Rich Harris <[email protected]> Co-authored-by: Conduitry <[email protected]>
1 parent de3be9a commit 1cd93cd

File tree

6 files changed

+25
-7
lines changed

6 files changed

+25
-7
lines changed

.changeset/tidy-owls-enter.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: ignore route groups when generating typed routes

packages/kit/src/core/sync/write_types/index.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,18 @@ import { posixify, rimraf, walk } from '../../../utils/filesystem.js';
66
import { compact } from '../../../utils/array.js';
77
import { ts } from '../ts.js';
88
import { s } from '../../../utils/misc.js';
9+
import { get_route_segments } from '../../../utils/routing.js';
910

1011
const remove_relative_parent_traversals = (/** @type {string} */ path) =>
1112
path.replace(/\.\.\//g, '');
1213
const replace_optional_params = (/** @type {string} */ id) =>
1314
id.replace(/\/\[\[[^\]]+\]\]/g, '${string}');
1415
const replace_required_params = (/** @type {string} */ id) =>
1516
id.replace(/\/\[[^\]]+\]/g, '/${string}');
17+
/** Convert route ID to pathname by removing layout groups */
18+
const remove_group_segments = (/** @type {string} */ id) => {
19+
return '/' + get_route_segments(id).join('/');
20+
};
1621
const is_whitespace = (/** @type {string} */ char) => /\s/.test(char);
1722

1823
/**
@@ -60,8 +65,8 @@ export function write_all_types(config, manifest_data) {
6065
}
6166
}
6267

63-
/** @type {string[]} */
64-
const pathnames = [];
68+
/** @type {Set<string>} */
69+
const pathnames = new Set();
6570

6671
/** @type {string[]} */
6772
const dynamic_routes = [];
@@ -76,9 +81,11 @@ export function write_all_types(config, manifest_data) {
7681

7782
dynamic_routes.push(route_type);
7883

79-
pathnames.push(`\`${replace_required_params(replace_optional_params(route.id))}\` & {}`);
84+
const pathname = remove_group_segments(route.id);
85+
pathnames.add(`\`${replace_required_params(replace_optional_params(pathname))}\` & {}`);
8086
} else {
81-
pathnames.push(s(route.id));
87+
const pathname = remove_group_segments(route.id);
88+
pathnames.add(s(pathname));
8289
}
8390

8491
/** @type {Map<string, boolean>} */
@@ -113,7 +120,7 @@ export function write_all_types(config, manifest_data) {
113120
`export type RouteId = ${manifest_data.routes.map((r) => s(r.id)).join(' | ')};`,
114121
'export type RouteParams<T extends RouteId> = T extends keyof DynamicRoutes ? DynamicRoutes[T] : Record<string, never>;',
115122
'export type LayoutParams<T extends RouteId> = Layouts[T] | Record<string, never>;',
116-
`export type Pathname = ${pathnames.join(' | ')};`,
123+
`export type Pathname = ${Array.from(pathnames).join(' | ')};`,
117124
'export type ResolvedPathname = `${"" | `/${string}`}${Pathname}`;',
118125
`export type Asset = ${manifest_data.assets.map((asset) => s('/' + asset.file)).join(' | ') || 'never'};`
119126
].join('\n\n')

packages/kit/src/core/sync/write_types/index.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function run_test(dir) {
3030
write_all_types(initial, manifest);
3131
}
3232

33-
test('Creates correct $types', { timeout: 6000 }, () => {
33+
test('Creates correct $types', { timeout: 10000 }, () => {
3434
// To save us from creating a real SvelteKit project for each of the tests,
3535
// we first run the type generation directly for each test case, and then
3636
// call `tsc` to check that the generated types are valid.

packages/kit/src/core/sync/write_types/test/app-types/(group)/path-a/+page.ts

Whitespace-only changes.

packages/kit/src/core/sync/write_types/test/app-types/+page.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ declare let id: RouteId;
55
// okay
66
id = '/';
77
id = '/foo/[bar]/[baz]';
8+
id = '/(group)/path-a';
89

910
// @ts-expect-error
1011
id = '/nope';
@@ -26,5 +27,10 @@ pathname = '/nope';
2627
pathname = '/foo';
2728
pathname = '/foo/1/2';
2829

30+
// Test layout groups
31+
pathname = '/path-a';
32+
// @ts-expect-error layout group names are NOT part of the pathname type
33+
pathname = '/(group)/path-a';
34+
2935
// read `pathname` otherwise it is treated as unused
3036
pathname;

packages/kit/src/utils/routing.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export function remove_optional_params(id) {
117117
* @param {string} segment
118118
*/
119119
function affects_path(segment) {
120-
return !/^\([^)]+\)$/.test(segment);
120+
return segment !== '' && !/^\([^)]+\)$/.test(segment);
121121
}
122122

123123
/**

0 commit comments

Comments
 (0)