Skip to content

Instantly share code, notes, and snippets.

View phenomnomnominal's full-sized avatar
🥑
Hangry

Craig Spence phenomnomnominal

🥑
Hangry
View GitHub Profile
// Dependencies:
import { tsquery } from '@phenomnomnominal/tsquery';
import { RuleFailure, Rules } from 'tslint';
import { SourceFile } from 'typescript';
// Constants:
const CATCH_ERROR_QUERY = 'ClassDeclaration > PropertyDeclaration:has(Decorator Identifier[name="Effect"]) > CallExpression > CallExpression > Identifier[name="catchError"]';
const FAILURE_MESSAGE = `
@phenomnomnominal
phenomnomnominal / example.md
Last active January 29, 2019 18:53
Content projection as inversion of control

Before:

class Car {
    private _engine: Engine;
    private _radio: Radio;
    
    constructor () {
        this._engine = new Engine();
 this._radio = new Radio();
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})`;