Peter Bacon Darwin d6791ff0e0 feat(ngUpgrade): add support for AoT compiled upgrade applications
This commit introduces a new API to the ngUpgrade module, which is compatible
with AoT compilation. Primarily, it removes the dependency on reflection
over the Angular 2 metadata by introducing an API where this information
is explicitly defined, in the source code, in a way that is not lost through
AoT compilation.

This commit is a collaboration between @mhevery (who provided the original
design of the API); @gkalpak & @petebacondarwin (who implemented the
API and migrated the specs from the original ngUpgrade tests) and @alexeagle
(who provided input and review).

This commit is an starting point, there is still work to be done:

* add more documentation
* validate the API via internal projects
* align the ngUpgrade compilation of A1 directives closer to the real A1
  compiler
* add more unit tests
* consider support for async `templateUrl` A1 upgraded components

Closes #12239
2016-10-19 15:27:49 -07:00

72 lines
2.0 KiB
TypeScript

/**
* @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 {DirectiveResolver} from '@angular/compiler';
import {Directive, Type} from '@angular/core';
var COMPONENT_SELECTOR = /^[\w|-]*$/;
var SKEWER_CASE = /-(\w)/g;
var directiveResolver = new DirectiveResolver();
export interface AttrProp {
prop: string;
attr: string;
bracketAttr: string;
bracketParenAttr: string;
parenAttr: string;
onAttr: string;
bindAttr: string;
bindonAttr: string;
}
export interface ComponentInfo {
type: Type<any>;
selector: string;
inputs?: AttrProp[];
outputs?: AttrProp[];
}
export function getComponentInfo(type: Type<any>): ComponentInfo {
var resolvedMetadata: Directive = directiveResolver.resolve(type);
var selector = resolvedMetadata.selector;
if (!selector.match(COMPONENT_SELECTOR)) {
throw new Error('Only selectors matching element names are supported, got: ' + selector);
}
selector = selector.replace(
SKEWER_CASE, (all: any /** TODO #9100 */, letter: string) => letter.toUpperCase());
return {
type: type,
selector: selector,
inputs: parseFields(resolvedMetadata.inputs),
outputs: parseFields(resolvedMetadata.outputs)
};
}
export function parseFields(names: string[]): AttrProp[] {
var attrProps: AttrProp[] = [];
if (names) {
for (var i = 0; i < names.length; i++) {
var parts = names[i].split(':');
var prop = parts[0].trim();
var attr = (parts[1] || parts[0]).trim();
var capitalAttr = attr.charAt(0).toUpperCase() + attr.substr(1);
attrProps.push(<AttrProp>{
prop: prop,
attr: attr,
bracketAttr: `[${attr}]`,
parenAttr: `(${attr})`,
bracketParenAttr: `[(${attr})]`,
onAttr: `on${capitalAttr}`,
bindAttr: `bind${capitalAttr}`,
bindonAttr: `bindon${capitalAttr}`
});
}
}
return attrProps;
}