Skip to content

Instantly share code, notes, and snippets.

View phenomnomnominal's full-sized avatar
🥑
Hangry

Craig Spence phenomnomnominal

🥑
Hangry
View GitHub Profile
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
RouterModule.forChild([{
path: '',
loadChildren: './lazy/lazy.module#LazyModule'
}])
]
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
RouterModule.forChild([{
path: '',
loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule)
}])
]
@NgModule({declarations: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES})
export class RouterModule {
// ...
static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders {
return {
ngModule: RouterModule,
providers: [
// ...
provideRoutes(routes),
export const ROUTES = new InjectionToken<Route[][]>('ROUTES');
export class RouterConfigLoader {
// ...
load(parentInjector: Injector, route: Route): Observable<LoadedRouterConfig> {
// ...
const moduleFactory$ = this.loadModuleFactory(route.loadChildren !);
// ...
}
/**
* A function that is called to resolve a collection of lazy-loaded routes.
*/
export type LoadChildrenCallback = () => Type<any>| NgModuleFactory<any>| Promise<Type<any>>| Observable<Type<any>>;
/**
* A string of the form `path/to/file#exportName` that acts as a URL for a set of routes to load,
* or a function that returns such a set.
*/
export type LoadChildren = string | LoadChildrenCallback;
export class RouterConfigLoader {
// ...
private loadModuleFactory(loadChildren: LoadChildren): Observable<NgModuleFactory<any>> {
if (typeof loadChildren === 'string') {
// ...
} else {
return wrapIntoObservable(loadChildren()).pipe(mergeMap((t: any) => {
if (t instanceof NgModuleFactory) {
return of (t);
} else {
export function listLazyRoutes(
moduleMeta: CompileNgModuleMetadata, reflector: StaticReflector): LazyRoute[] {
const allLazyRoutes: LazyRoute[] = [];
for (const {provider, module} of moduleMeta.transitiveModule.providers) {
if (tokenReference(provider.token) === reflector.ROUTES) {
const loadChildren = _collectLoadChildren(provider.useValue);
for (const route of loadChildren) {
allLazyRoutes.push(parseLazyRoute(route, reflector, module.reference));
}
}
// Dependencies:
import { tsquery } from '@phenomnomnominal/tsquery';
import { Replacement, RuleFailure, Rules } from 'tslint';
import { SourceFile } from 'typescript';
// Constants:
const LOAD_CHILDREN_SPLIT = '#';
const LOAD_CHILDREN_VALUE_QUERY = `StringLiteral[value=/.*${LOAD_CHILDREN_SPLIT}.*/]`;
const LOAD_CHILDREN_ASSIGNMENT_QUERY = `PropertyAssignment:not(:has(Identifier[name="children"])):has(Identifier[name="loadChildren"]):has(${LOAD_CHILDREN_VALUE_QUERY})`;
// Constants:
const LOAD_CHILDREN_VALUE_QUERY = `StringLiteral[value=/.*${LOAD_CHILDREN_SPLIT}.*/]`;
const LOAD_CHILDREN_ASSIGNMENT_QUERY = `PropertyAssignment:not(:has(Identifier[name="children"])):has(Identifier[name="loadChildren"]):has(${LOAD_CHILDREN_VALUE_QUERY})`;
export class Rule extends Rules.AbstractRule {
public apply(sourceFile: SourceFile): Array<RuleFailure> {
const options = this.getOptions();
const [preferAsync] = options.ruleArguments;
return tsquery(sourceFile, LOAD_CHILDREN_ASSIGNMENT_QUERY).map(result => {
export class Rule extends Rules.AbstractRule {
public apply(sourceFile: SourceFile): Array<RuleFailure> {
// ...
let fix = preferAsync === 'async' ? this._asyncReplacement(valueNode.text) : this._promiseReplacement(valueNode.text);
// ...
}
private _promiseReplacement (loadChildren: string): string {
const [path, moduleName] = this._getChunks(loadChildren);
return `() => import('${path}').then(m => m.${moduleName})`;