Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(linker): Allow configurable module prefixes and suffixes. #11049

Merged
merged 1 commit into from Aug 24, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/@angular/core/src/linker.ts
Expand Up @@ -15,7 +15,7 @@ export {ExpressionChangedAfterItHasBeenCheckedException} from './linker/exceptio
export {NgModuleFactory, NgModuleRef} from './linker/ng_module_factory';
export {NgModuleFactoryLoader} from './linker/ng_module_factory_loader';
export {QueryList} from './linker/query_list';
export {SystemJsNgModuleLoader} from './linker/system_js_ng_module_factory_loader';
export {SystemJsNgModuleLoader, SystemJsNgModuleLoaderConfig} from './linker/system_js_ng_module_factory_loader';
export {TemplateRef} from './linker/template_ref';
export {ViewContainerRef} from './linker/view_container_ref';
export {EmbeddedViewRef, ViewRef} from './linker/view_ref';
Expand Up @@ -7,24 +7,56 @@
*/


import {Injectable} from '../di';
import {Injectable, Optional} from '../di';

import {Compiler} from './compiler';
import {NgModuleFactory} from './ng_module_factory';
import {NgModuleFactoryLoader} from './ng_module_factory_loader';

const _SEPARATOR = '#';

const FACTORY_MODULE_SUFFIX = '.ngfactory';
const FACTORY_CLASS_SUFFIX = 'NgFactory';

/**
* Configuration for SystemJsNgModuleLoader.
* token.
*
* @experimental
*/
export abstract class SystemJsNgModuleLoaderConfig {
/**
* Prefix to add when computing the name of the factory module for a given module name.
*/
factoryPathPrefix: string;

/**
* Suffix to add when computing the name of the factory module for a given module name.
*/
factoryPathSuffix: string;
}

const DEFAULT_CONFIG: SystemJsNgModuleLoaderConfig = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could use default class property values if you used the approach I described above.

factoryPathPrefix: '',
factoryPathSuffix: '.ngfactory',
};

/**
* NgModuleFactoryLoader that uses SystemJS to load NgModuleFactory
* @experimental
*/
@Injectable()
export class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
constructor(private _compiler: Compiler) {}
private _config: SystemJsNgModuleLoaderConfig;

/**
* @internal
*/
_system: any;

constructor(private _compiler: Compiler, @Optional() config?: SystemJsNgModuleLoaderConfig) {
this._system = () => System;
this._config = config || DEFAULT_CONFIG;
}

load(path: string): Promise<NgModuleFactory<any>> {
const offlineMode = this._compiler instanceof Compiler;
Expand All @@ -35,18 +67,24 @@ export class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
let [module, exportName] = path.split(_SEPARATOR);
if (exportName === undefined) exportName = 'default';

return System.import(module)
return this._system()
.import(module)
.then((module: any) => module[exportName])
.then((type: any) => checkNotEmpty(type, module, exportName))
.then((type: any) => this._compiler.compileModuleAsync(type));
}

private loadFactory(path: string): Promise<NgModuleFactory<any>> {
let [module, exportName] = path.split(_SEPARATOR);
if (exportName === undefined) exportName = 'default';
let factoryClassSuffix = FACTORY_CLASS_SUFFIX;
if (exportName === undefined) {
exportName = 'default';
factoryClassSuffix = '';
}

return System.import(module + FACTORY_MODULE_SUFFIX)
.then((module: any) => module[exportName + FACTORY_CLASS_SUFFIX])
return this._system()
.import(this._config.factoryPathPrefix + module + this._config.factoryPathSuffix)
.then((module: any) => module[exportName + factoryClassSuffix])
.then((factory: any) => checkNotEmpty(factory, module, exportName));
}
}
Expand Down
@@ -0,0 +1,49 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Compiler, SystemJsNgModuleLoader} from '@angular/core';
import {async, tick} from '@angular/core/testing';
import {beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';

function mockSystem(module: string, contents: any) {
return {
'import': (target: string) => {
expect(target).toBe(module);
return Promise.resolve(contents);
}
};
}

export function main() {
describe('SystemJsNgModuleLoader', () => {
it('loads a default factory by appending the factory suffix', async(() => {
let loader = new SystemJsNgModuleLoader(new Compiler());
loader._system = () => mockSystem('test.ngfactory', {'default': 'test module factory'});
loader.load('test').then(contents => { expect(contents).toBe('test module factory'); });
}));
it('loads a named factory by appending the factory suffix', async(() => {
let loader = new SystemJsNgModuleLoader(new Compiler());
loader._system = () =>
mockSystem('test.ngfactory', {'NamedNgFactory': 'test module factory'});
loader.load('test#Named').then(contents => {
expect(contents).toBe('test module factory');
});
}));
it('loads a named factory with a configured prefix and suffix', async(() => {
let loader = new SystemJsNgModuleLoader(new Compiler(), {
factoryPathPrefix: 'prefixed/',
factoryPathSuffix: '/suffixed',
});
loader._system = () =>
mockSystem('prefixed/test/suffixed', {'NamedNgFactory': 'test module factory'});
loader.load('test#Named').then(contents => {
expect(contents).toBe('test module factory');
});
}));
});
};
8 changes: 7 additions & 1 deletion tools/public_api_guard/core/index.d.ts
Expand Up @@ -1158,10 +1158,16 @@ export declare function style(tokens: string | {

/** @experimental */
export declare class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
constructor(_compiler: Compiler);
constructor(_compiler: Compiler, config?: SystemJsNgModuleLoaderConfig);
load(path: string): Promise<NgModuleFactory<any>>;
}

/** @experimental */
export declare abstract class SystemJsNgModuleLoaderConfig {
factoryPathPrefix: string;
factoryPathSuffix: string;
}

/** @stable */
export declare abstract class TemplateRef<C> {
elementRef: ElementRef;
Expand Down