refactor(@angular/ssr): replace :params with *

The SSR router relies on wildcard matching rather than params. This commit refactors the stored routes by removing the `:params`.
This commit is contained in:
Alan Agius 2024-11-22 10:18:58 +00:00 committed by Douglas Parker
parent e7d3b72acc
commit 20411f696e
3 changed files with 13 additions and 11 deletions

View File

@ -576,7 +576,7 @@ export async function extractRoutesAndCreateRouteTree(
} }
const fullRoute = joinUrlParts(baseHref, route); const fullRoute = joinUrlParts(baseHref, route);
routeTree.insert(fullRoute.replace(URL_PARAMETER_REGEXP, '*'), metadata); routeTree.insert(fullRoute, metadata);
} }
return { return {

View File

@ -131,6 +131,7 @@ export class RouteTree<AdditionalMetadata extends Record<string, unknown> = {}>
insert(route: string, metadata: RouteTreeNodeMetadataWithoutRoute & AdditionalMetadata): void { insert(route: string, metadata: RouteTreeNodeMetadataWithoutRoute & AdditionalMetadata): void {
let node = this.root; let node = this.root;
const segments = this.getPathSegments(route); const segments = this.getPathSegments(route);
const normalizedSegments: string[] = [];
for (const segment of segments) { for (const segment of segments) {
// Replace parameterized segments (e.g., :id) with a wildcard (*) for matching // Replace parameterized segments (e.g., :id) with a wildcard (*) for matching
@ -143,12 +144,13 @@ export class RouteTree<AdditionalMetadata extends Record<string, unknown> = {}>
} }
node = childNode; node = childNode;
normalizedSegments.push(normalizedSegment);
} }
// At the leaf node, store the full route and its associated metadata // At the leaf node, store the full route and its associated metadata
node.metadata = { node.metadata = {
...metadata, ...metadata,
route: segments.join('/'), route: normalizedSegments.join('/'),
}; };
node.insertionIndex = this.insertionIndexCounter++; node.insertionIndex = this.insertionIndexCounter++;

View File

@ -30,7 +30,7 @@ describe('RouteTree', () => {
expect(routeTreeObj).toEqual([ expect(routeTreeObj).toEqual([
{ redirectTo: '/home-page', route: '/home', renderMode: RenderMode.Server }, { redirectTo: '/home-page', route: '/home', renderMode: RenderMode.Server },
{ redirectTo: '/about-page', route: '/about', renderMode: RenderMode.Server }, { redirectTo: '/about-page', route: '/about', renderMode: RenderMode.Server },
{ route: '/products/:id', renderMode: RenderMode.Server }, { route: '/products/*', renderMode: RenderMode.Server },
{ redirectTo: '/api/details-page', route: '/api/details', renderMode: RenderMode.Server }, { redirectTo: '/api/details-page', route: '/api/details', renderMode: RenderMode.Server },
]); ]);
@ -46,7 +46,7 @@ describe('RouteTree', () => {
renderMode: RenderMode.Server, renderMode: RenderMode.Server,
}); });
expect(newRouteTree.match('/products/123')).toEqual({ expect(newRouteTree.match('/products/123')).toEqual({
route: '/products/:id', route: '/products/*',
renderMode: RenderMode.Server, renderMode: RenderMode.Server,
}); });
expect(newRouteTree.match('/api/details')).toEqual({ expect(newRouteTree.match('/api/details')).toEqual({
@ -71,7 +71,7 @@ describe('RouteTree', () => {
expect(newRouteTree.match('/shop/categories/electronics/products/123')).toEqual({ expect(newRouteTree.match('/shop/categories/electronics/products/123')).toEqual({
redirectTo: '/shop/products', redirectTo: '/shop/products',
route: '/shop/categories/:category/products/:id', route: '/shop/categories/*/products/*',
renderMode: RenderMode.Server, renderMode: RenderMode.Server,
}); });
expect(newRouteTree.match('/shop/cart')).toEqual({ expect(newRouteTree.match('/shop/cart')).toEqual({
@ -127,7 +127,7 @@ describe('RouteTree', () => {
const routeTreeObj = routeTree.toObject(); const routeTreeObj = routeTree.toObject();
expect(routeTreeObj).toEqual([ expect(routeTreeObj).toEqual([
{ route: '/first', renderMode: RenderMode.Server }, { route: '/first', renderMode: RenderMode.Server },
{ route: '/:id', renderMode: RenderMode.Server }, { route: '/*', renderMode: RenderMode.Server },
{ route: '/second', renderMode: RenderMode.Server }, { route: '/second', renderMode: RenderMode.Server },
]); ]);
@ -137,11 +137,11 @@ describe('RouteTree', () => {
renderMode: RenderMode.Server, renderMode: RenderMode.Server,
}); });
expect(newRouteTree.match('/second')).toEqual({ expect(newRouteTree.match('/second')).toEqual({
route: '/:id', route: '/*',
renderMode: RenderMode.Server, renderMode: RenderMode.Server,
}); });
expect(newRouteTree.match('/third')).toEqual({ expect(newRouteTree.match('/third')).toEqual({
route: '/:id', route: '/*',
renderMode: RenderMode.Server, renderMode: RenderMode.Server,
}); });
}); });
@ -217,7 +217,7 @@ describe('RouteTree', () => {
it('should handle parameterized segments as wildcards', () => { it('should handle parameterized segments as wildcards', () => {
routeTree.insert('/users/:id', { renderMode: RenderMode.Server }); routeTree.insert('/users/:id', { renderMode: RenderMode.Server });
expect(routeTree.match('/users/123')).toEqual({ expect(routeTree.match('/users/123')).toEqual({
route: '/users/:id', route: '/users/*',
renderMode: RenderMode.Server, renderMode: RenderMode.Server,
}); });
}); });
@ -229,11 +229,11 @@ describe('RouteTree', () => {
}); });
expect(routeTree.match('/shop/categories/electronics')).toEqual({ expect(routeTree.match('/shop/categories/electronics')).toEqual({
route: '/shop/categories/:category', route: '/shop/categories/*',
renderMode: RenderMode.Server, renderMode: RenderMode.Server,
}); });
expect(routeTree.match('/shop/categories/electronics/products/456')).toEqual({ expect(routeTree.match('/shop/categories/electronics/products/456')).toEqual({
route: '/shop/categories/:category/products/:id', route: '/shop/categories/*/products/*',
renderMode: RenderMode.Server, renderMode: RenderMode.Server,
}); });
}); });