-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(upgrade): add ngUpgrade integration support (#116)
Closes #83
- Loading branch information
1 parent
5c57427
commit cdc86dc
Showing
12 changed files
with
573 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,5 @@ | ||
import { assertionsEnabled } from '../facade/lang'; | ||
import { bundle } from '../core/util/bundler'; | ||
import { createBootstrapFn } from './browser_utils' | ||
|
||
export * from './title'; | ||
export type AppRoot = string | Element | Document; | ||
|
||
/** | ||
* bootstrap angular app | ||
* @param {Type} rootComponent | ||
* @param {Array<any>} providers | ||
*/ | ||
export function bootstrap( | ||
rootComponent: Type, | ||
providers: any[] | ||
) { | ||
|
||
const ngModule = bundle( rootComponent, providers ); | ||
const ngModuleName = ngModule.name; | ||
const strictDi = true; | ||
const element = document; | ||
|
||
if ( assertionsEnabled() ) { | ||
console.info( | ||
'Angular is running in the development mode. Call enableProdMode() to enable the production mode.' | ||
); | ||
} else { | ||
angular.module( ngModuleName ).config( prodModeConfig ); | ||
} | ||
|
||
const appRoot = _getAppRoot( element ); | ||
|
||
angular.element( document ).ready( ()=> { | ||
angular.bootstrap( appRoot, [ ngModuleName ], { | ||
strictDi | ||
} ) | ||
} ); | ||
export const bootstrap = createBootstrapFn() | ||
|
||
} | ||
|
||
function _getAppRoot( element: AppRoot ): Element { | ||
|
||
if ( typeof element === 'string' ) { | ||
return document.querySelector( element ); | ||
} | ||
return element as Element; | ||
|
||
} | ||
|
||
prodModeConfig.$inject = [ '$compileProvider', '$httpProvider' ]; | ||
function prodModeConfig( $compileProvider: ng.ICompileProvider, $httpProvider: ng.IHttpProvider ) { | ||
$compileProvider.debugInfoEnabled( false ); | ||
$httpProvider.useApplyAsync( true ); | ||
} | ||
export * from './title'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { assertionsEnabled } from '../facade/lang'; | ||
import { bundle } from '../core/util/bundler'; | ||
|
||
type AppRoot = string | Element | Document; | ||
|
||
function _getAppRoot( element: AppRoot ): Element { | ||
|
||
if ( typeof element === 'string' ) { | ||
return document.querySelector( element ); | ||
} | ||
return element as Element; | ||
|
||
} | ||
|
||
prodModeConfig.$inject = [ '$compileProvider', '$httpProvider' ]; | ||
function prodModeConfig( $compileProvider: ng.ICompileProvider, $httpProvider: ng.IHttpProvider ) { | ||
$compileProvider.debugInfoEnabled( false ); | ||
$httpProvider.useApplyAsync( true ); | ||
} | ||
|
||
export function createBootstrapFn(bootstrapFn: Function = angular.bootstrap.bind(angular)): Function { | ||
|
||
/** | ||
* bootstrap angular app | ||
* @param {Type} rootComponent | ||
* @param {Array<any>} providers | ||
*/ | ||
return function bootstrap( | ||
rootComponent: Type, | ||
providers: any[] | ||
) { | ||
|
||
const ngModule = bundle( rootComponent, providers ); | ||
const ngModuleName = ngModule.name; | ||
const strictDi = true; | ||
const element = document; | ||
|
||
if ( assertionsEnabled() ) { | ||
console.info( | ||
'Angular is running in the development mode. Call enableProdMode() to enable the production mode.' | ||
); | ||
} else { | ||
angular.module( ngModuleName ).config( prodModeConfig ); | ||
} | ||
|
||
const appRoot = _getAppRoot( element ); | ||
|
||
angular.element( document ).ready( ()=> { | ||
bootstrapFn( appRoot, [ ngModuleName ], { | ||
strictDi | ||
} ) | ||
} ); | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/** | ||
* `UgradeAdapterRef` controls a hybrid AngularJS v1 / Angular v2 application, | ||
* but we don't have a use for it right now so no point in creating an interface for it... | ||
*/ | ||
export type UgradeAdapterRef = void; | ||
|
||
export interface UpgradeAdapter { | ||
new (): UpgradeAdapterInstance; | ||
} | ||
|
||
export interface UpgradeAdapterInstance { | ||
/** | ||
* Allows Angular v2 Component to be used from AngularJS v1. | ||
*/ | ||
downgradeNg2Component(type: Type): Function; | ||
/** | ||
* Bootstrap a hybrid AngularJS v1 / Angular v2 application. | ||
*/ | ||
bootstrap(element: Element, modules?: any[], config?: angular.IAngularBootstrapConfig): UgradeAdapterRef; | ||
/** | ||
* Adds a provider to the top level environment of a hybrid AngularJS v1 / Angular v2 application. | ||
*/ | ||
addProvider(provider: Type | any[] | any): void; | ||
/** | ||
* Allows Angular v2 service to be accessible from AngularJS v1. | ||
*/ | ||
downgradeNg2Provider(token: any): Function; | ||
/** | ||
* Allows AngularJS v1 service to be accessible from Angular v2. | ||
*/ | ||
upgradeNg1Provider(name: string, options?: { asToken: any; }): void; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import { UpgradeAdapter, UpgradeAdapterInstance } from './upgrade'; | ||
import { createBootstrapFn } from '../platform/browser_utils'; | ||
import { reflector } from '../core/reflection/reflection'; | ||
import { getInjectableName, OpaqueToken } from '../core/di'; | ||
import { ProviderLiteral } from '../core/di/provider_util'; | ||
import { resolveDirectiveNameFromSelector } from '../facade/lang'; | ||
|
||
export class NgMetadataUpgradeAdapter { | ||
|
||
bootstrap: Function; | ||
|
||
_upgradeAdapter: UpgradeAdapterInstance; | ||
|
||
constructor( UpgradeAdapter: UpgradeAdapter ) { | ||
/** | ||
* Manage the @angular/upgrade singleton | ||
*/ | ||
this._upgradeAdapter = new UpgradeAdapter(); | ||
/** | ||
* Used to bootstrap a hybrid Angular 1 and Angular 2 application, | ||
* using the same signature as `bootstrap` from ng-metadata/platform-browser-dynamic | ||
* | ||
* E.g. `upgradeAdapter.bootstrap(AppComponent, providers)` | ||
*/ | ||
this.bootstrap = createBootstrapFn(this._upgradeAdapter.bootstrap.bind(this._upgradeAdapter)); | ||
} | ||
|
||
/** | ||
* Used to register an Angular 2 component as a directive on an Angular 1 module, | ||
* where the directive name is automatically created from the selector. | ||
* | ||
* E.g. `.directive(...upgradeAdapter.downgradeNg2Component(Ng2Component)) | ||
*/ | ||
downgradeNg2Component( component: Type ): [ string, Function ] { | ||
const annotations = reflector.annotations( component ); | ||
const cmpAnnotation = annotations[ 0 ]; | ||
const directiveName = resolveDirectiveNameFromSelector( cmpAnnotation.selector ); | ||
return [ directiveName, this._upgradeAdapter.downgradeNg2Component( component ) ]; | ||
} | ||
|
||
/** | ||
* Used to register an Angular 2 component by including it in the directives array | ||
* of an ng-metadata annotated Angular 1 component. | ||
* | ||
* E.g. | ||
* ``` | ||
* @Component({ | ||
* selector: 'foo', | ||
* directives: [upgradeAdapter.provideNg2Component(Ng2Component)], | ||
* }) | ||
* ``` | ||
*/ | ||
provideNg2Component( component: Type ): Function { | ||
const [ directiveName, directiveFactory ] = this.downgradeNg2Component( component ); | ||
reflector.registerDowngradedNg2ComponentName( directiveName, directiveFactory ); | ||
return directiveFactory; | ||
} | ||
|
||
/** | ||
* Adds an Angular 2 provider to the hybrid application. | ||
*/ | ||
addProvider( provider: Type | any[] | any ): void { | ||
return this._upgradeAdapter.addProvider( provider ); | ||
} | ||
|
||
/** | ||
* Downgrades an Angular 2 Provider so that it can be registered as an Angular 1 | ||
* factory. Either a string or an ng-metadata OpaqueToken can be used for the name. | ||
* | ||
* E.g. | ||
* ``` | ||
* const otherServiceToken = new OpaqueToken('otherService') | ||
* | ||
* .factory(...upgradeAdapter.downgradeNg2Provider('ng2Service', { useClass: Ng2Service })) | ||
* .factory(...upgradeAdapter.downgradeNg2Provider(otherServiceToken, { useClass: Ng2Service })) | ||
* ``` | ||
*/ | ||
downgradeNg2Provider( name: string | OpaqueToken, options: { useClass: Type } ): [ string, Function ] { | ||
const downgradedProvider = this._upgradeAdapter.downgradeNg2Provider( options.useClass ); | ||
return [ getInjectableName(name), downgradedProvider ]; | ||
} | ||
|
||
/** | ||
* Returns a ProviderLiteral which can be used to register an Angular 2 Provider | ||
* by including it in the providers array of an ng-metadata annotated Angular 1 | ||
* component. Either a string or an ng-metadata OpaqueToken can be used for the name. | ||
* | ||
* E.g. | ||
* ``` | ||
* const otherServiceToken = new OpaqueToken('otherService') | ||
* | ||
* @Component({ | ||
* selector: 'foo', | ||
* providers: [ | ||
* upgradeAdapter.provideNg2Provider('ng2Service', { useClass: Ng2Service }) | ||
* upgradeAdapter.provideNg2Provider(otherServiceToken, { useClass: Ng2Service }) | ||
* ], | ||
* }) | ||
* ``` | ||
*/ | ||
provideNg2Provider( name: string | OpaqueToken, options: { useClass: Type } ): ProviderLiteral { | ||
const downgradedProvider = this._upgradeAdapter.downgradeNg2Provider( options.useClass ); | ||
return { | ||
provide: getInjectableName(name), | ||
useFactory: downgradedProvider, | ||
deps: downgradedProvider.$inject, | ||
}; | ||
} | ||
|
||
/** | ||
* Used to make an Angular 1 Provider available to Angular 2 Components and Providers. | ||
* When using the upgraded Provider for DI, either the string name can be used with @Inject, or | ||
* a given token can be injected by type. | ||
* | ||
* E.g. | ||
* class $state {} | ||
* | ||
* upgradeAdapter.upgradeNg1Provider('$state', { asToken: $state }) | ||
* upgradeAdapter.upgradeNg1Provider('$rootScope') | ||
* | ||
* @Component({ | ||
* selector: 'ng2', | ||
* template: `<h1>Ng2</h1>`, | ||
* }) | ||
* class Ng2Component { | ||
* constructor( | ||
* @Inject('$rootScope') private $rootScope: any, // by name using @Inject | ||
* private $state: $state // by type using the user defined token | ||
* ) {} | ||
* } | ||
* | ||
*/ | ||
upgradeNg1Provider( name: string, options?: { asToken: any; } ): void { | ||
return this._upgradeAdapter.upgradeNg1Provider( name, options ); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.