Skip to content

Commit 6e54bdf

Browse files
aparzithePunderWoman
authored andcommitted
fix(migrations): fix route-lazy-loading migration (#63818)
route-lazy-loading migration now supports routes when exported by default PR Close #63818
1 parent 0afd9c5 commit 6e54bdf

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

packages/core/schematics/ng-generate/route-lazy-loading/to-lazy-routes.ts

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,7 @@ function findRoutesArrayToMigrate(sourceFile: ts.SourceFile, typeChecker: ts.Typ
117117
}
118118
}
119119
}
120-
}
121-
122-
if (ts.isVariableDeclaration(node)) {
120+
} else if (ts.isVariableDeclaration(node)) {
123121
if (isAngularRoutesArray(node, typeChecker)) {
124122
const initializer = node.initializer;
125123
if (
@@ -140,6 +138,37 @@ function findRoutesArrayToMigrate(sourceFile: ts.SourceFile, typeChecker: ts.Typ
140138
});
141139
}
142140
}
141+
} else if (ts.isExportAssignment(node)) {
142+
// Handles `export default routes`, `export default [...]` and `export default [...] as Routes`
143+
let expression = node.expression;
144+
145+
if (ts.isAsExpression(expression)) {
146+
expression = expression.expression;
147+
}
148+
149+
if (ts.isArrayLiteralExpression(expression)) {
150+
routesArrays.push({
151+
routeFilePath: sourceFile.fileName,
152+
array: expression,
153+
routeFileImports: sourceFile.statements.filter(ts.isImportDeclaration),
154+
});
155+
} else if (ts.isIdentifier(expression)) {
156+
manageRoutesExportedByDefault(routesArrays, typeChecker, expression, sourceFile);
157+
}
158+
} else if (ts.isExportDeclaration(node)) {
159+
// Handles cases like `export { routes as default }`
160+
if (node.exportClause && ts.isNamedExports(node.exportClause)) {
161+
for (const specifier of node.exportClause.elements) {
162+
if (specifier.name.text === 'default') {
163+
manageRoutesExportedByDefault(
164+
routesArrays,
165+
typeChecker,
166+
specifier.propertyName ?? specifier.name,
167+
sourceFile,
168+
);
169+
}
170+
}
171+
}
143172
}
144173

145174
node.forEachChild(walk);
@@ -325,6 +354,31 @@ function createLoadComponentPropertyAssignment(
325354
);
326355
}
327356

357+
const manageRoutesExportedByDefault = (
358+
routesArrays: RouteData[],
359+
typeChecker: ts.TypeChecker,
360+
expression: ts.Expression,
361+
sourceFile: ts.SourceFile,
362+
) => {
363+
const symbol = typeChecker.getSymbolAtLocation(expression);
364+
if (!symbol?.declarations) {
365+
return;
366+
}
367+
for (const declaration of symbol.declarations) {
368+
if (
369+
ts.isVariableDeclaration(declaration) &&
370+
declaration.initializer &&
371+
ts.isArrayLiteralExpression(declaration.initializer)
372+
) {
373+
routesArrays.push({
374+
routeFilePath: sourceFile.fileName,
375+
array: declaration.initializer,
376+
routeFileImports: sourceFile.statements.filter(ts.isImportDeclaration),
377+
});
378+
}
379+
}
380+
};
381+
328382
// import('./path)
329383
const createImportCallExpression = (componentImportPath: string) =>
330384
ts.factory.createCallExpression(ts.factory.createIdentifier('import'), undefined, [

packages/core/schematics/test/standalone_routes_spec.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,54 @@ describe('route lazy loading migration', () => {
804804
expect(error).toMatch(/Could not find any files to migrate under the path/);
805805
});
806806

807+
it('should migrate if routes are exported as default', async () => {
808+
writeFile(
809+
'app.module.ts',
810+
`
811+
import {NgModule} from '@angular/core';
812+
import {RouterModule} from '@angular/router';
813+
import {routes} from './routes';
814+
815+
@NgModule({
816+
imports: [RouterModule.forRoot(routes],
817+
})
818+
export class AppModule {}
819+
`,
820+
);
821+
822+
writeFile(
823+
'routes.ts',
824+
`
825+
import {Routes, Route} from '@angular/router';
826+
import {TestComponent} from './test';
827+
export default [
828+
{path: 'test', component: TestComponent}
829+
] as Routes;
830+
`,
831+
);
832+
833+
writeFile(
834+
'test.ts',
835+
`
836+
import {Component} from '@angular/core';
837+
@Component({template: 'hello', standalone: true})
838+
export class TestComponent {}
839+
`,
840+
);
841+
842+
await runMigration('route-lazy-loading');
843+
844+
expect(stripWhitespace(tree.readContent('routes.ts'))).toContain(
845+
stripWhitespace(`
846+
import {Routes, Route} from '@angular/router';
847+
848+
export default [
849+
{path: 'test', loadComponent: () => import('./test').then(m => m.TestComponent)}
850+
] as Routes;
851+
`),
852+
);
853+
});
854+
807855
xit('should migrate routes if the routes file in is another file without type', async () => {
808856
writeFile(
809857
'app.module.ts',

0 commit comments

Comments
 (0)