UNPKG

angular-ide

Version:

Provides a seamless integration with the Angular IDE from the command-line for developers looking for an enhanced development experience with Angular.

852 lines (683 loc) 30 kB
const path = require('path'); const ts = require('typescript'); const semver = require('semver'); const slashes = require('slashes'); const debug = require('debug')('angular-ide'); const chalk = require('chalk'); const ngCLIPKG = getNGCLIManifest(); // Make sure that we have a valid manifest structure let ngCLIPKGName = null; if (ngCLIPKG !== null) { ngCLIPKGName = ngCLIPKG.name; } const ngCLIPath = getNGCLIPath(ngCLIPKGName); const CLEnablementStatusManager = require('./CLEnablementStatusManager').CLEnablementStatusManager; const CLBootstrapInjectorPlugin = require('./CLBootstrapInjectorPlugin'); const fs = require('fs'); // AST Helper functions function convertValueToLiteral(val) { if (Array.isArray(val)) { return arrayToArrayLiteral(val); } if (typeof val === 'object') { return objectToObjectLiteral(val); } return ts.createLiteral(val); } function arrayToArrayLiteral(list) { const newList = list.map(convertValueToLiteral); return ts.createArrayLiteral(newList); } function objectToObjectLiteral(obj) { const newProperties = Object.keys(obj).map((key) => { return ts.createPropertyAssignment(ts.createLiteral(key), convertValueToLiteral(obj[key])); }); return ts.createObjectLiteral(newProperties); } function _getContentOfKeyLiteral(source, node) { if (node.kind == ts.SyntaxKind.Identifier) { return node.text; } else if (node.kind == ts.SyntaxKind.StringLiteral) { return node.text; } else { return null; } } function injectComponentMetadata_1() { let TypeScriptFileRefactor = null; try { TypeScriptFileRefactor = require('@ngtools/webpack/src/refactor'); } catch (e) { TypeScriptFileRefactor = require('@angular/cli/node_modules/@ngtools/webpack/src/refactor'); require.cache['@ngtools/webpack/src/refactor'] = require('@angular/cli/node_modules/@ngtools/webpack/src/refactor'); } const origFun = TypeScriptFileRefactor.TypeScriptFileRefactor; TypeScriptFileRefactor.TypeScriptFileRefactor = function (fileName, _host, _program) { const origInstance = new (Function.prototype.bind.apply(origFun, [this, fileName, _host, _program])); const _self = origInstance; (function (c) { if (c) { const sourceFile = _self.sourceFile; const styleUrls = []; let templateUrl = null; // Find all object literals. _self.findAstNodes(sourceFile, ts.SyntaxKind.ObjectLiteralExpression, true) .map(function (node) { return _self.findAstNodes(node, ts.SyntaxKind.PropertyAssignment); }) .reduce(function (prev, curr) { return curr ? prev.concat(curr) : prev; }, []) .filter(function (node) { const key = _getContentOfKeyLiteral(sourceFile, node.name); if (!key) { // key is an expression, can't do anything. return false; } return key == 'templateUrl' || key == 'styleUrls'; }) .forEach(function (node) { let key = _getContentOfKeyLiteral(sourceFile, node.name); if (key == 'templateUrl') { let templateUrlNode = _self.findAstNodes(node, ts.SyntaxKind.StringLiteral, false); if (!templateUrlNode || !templateUrlNode.length || !templateUrlNode[0].text) { return; } templateUrl = path.normalize(path.join( path.dirname(sourceFile.fileName), templateUrlNode[0].text )); } else if (key == 'styleUrls') { const arr = (_self.findAstNodes(node, ts.SyntaxKind.ArrayLiteralExpression, false)); if (!arr || arr.length == 0 || arr[0].elements.length == 0) { return; } arr.forEach(function (arrElement) { const dirName = path.dirname(sourceFile.fileName); let styleUrl = path.normalize(path.join(dirName, arrElement.elements[0].text)); styleUrls.push(styleUrl); }); const initializer = arr[0].elements.map(function (element) { return element.getFullText(sourceFile); }); } }); let isAComponent = false; if (sourceFile.identifiers) { if (typeof sourceFile.identifiers.Component !== 'undefined') { isAComponent = true; } if (!isAComponent && typeof sourceFile.identifiers.get === 'function') { isAComponent = sourceFile.identifiers.get('Component') } } if (isAComponent) { _self.findAstNodes(sourceFile, ts.SyntaxKind.ClassDeclaration, true) .forEach(function (node) { let tsPath = path.normalize(sourceFile.fileName); const metadataToInject = { componentPath: tsPath, styleUrls: styleUrls, }; if (templateUrl !== null) { metadataToInject.templateUrl = templateUrl; } const textToInject = `__clMeta = ${JSON.stringify(metadataToInject)};`; _self.insertAt(node.members.pos, textToInject); }); } } })(CLEnablementStatusManager.getStatus()); return _self; }; TypeScriptFileRefactor.TypeScriptFileRefactor.prototype = origFun.prototype; TypeScriptFileRefactor.TypeScriptFileRefactor.prototype.insertAt = function (pos, text) { if (this._sourceString.prependRight) { //get rid of warning logged during build this._sourceString.prependRight(pos, text); } else { this._sourceString.insertRight(pos, text); } this._changed = true; }; } function injectComponentMetadata_2() { const NgCliWebpackConfig = require(`${ngCLIPath}/models/webpack-config`).NgCliWebpackConfig; NgCliWebpackConfig.prototype.originalGetTargetConfig = NgCliWebpackConfig.prototype.getTargetConfig; NgCliWebpackConfig.prototype.getTargetConfig = function monkeyPatchedGenerateConfig(projectRoot, appConfig) { const targetConfig = this.originalGetTargetConfig(projectRoot, appConfig); if (typeof targetConfig.module === 'undefined') { targetConfig.module = { rules: [] }; } if (typeof targetConfig.module.rules === 'undefined') { targetConfig.module.rules = []; } targetConfig.module.rules.push({ enforce: 'pre', test: /\.(ts)$/, loader: 'angular-ide-loader' }); return targetConfig; }; } function injectComponentMetadata_3(ngtoolsPath) { try { AngularCompilerPluginModule = require(`${ngtoolsPath}/webpack/src/ivy/transformation`); require.cache['@ngtools/webpack/src/angular_compiler_plugin'] = require(`${ngtoolsPath}/webpack/src/ivy/transformation`); var originalCreateAotTransformers = AngularCompilerPluginModule.createAotTransformers; const ivyTransformer = require('./ivyTransformer'); AngularCompilerPluginModule.createAotTransformers = function (builder, options) { const transformers = originalCreateAotTransformers(builder, options); transformers.before.splice(0, 0, ivyTransformer(builder, options) ); return transformers; } } catch (e) { // no-op debug(chalk.yellow('Unable to patch ivy compiler')); debug(chalk.red(e)); debug(chalk.yellow('Trying to patch using legacy mode')) // Importing ngtools transformation helpers const make_transform_1 = require(`${ngtoolsPath}/webpack/src/transformers/make_transform`); const ast_helpers_1 = require(`${ngtoolsPath}/webpack/src/transformers/ast_helpers`); const interfaces_1 = require(`${ngtoolsPath}/webpack/src/transformers/interfaces`); // Keys used to find the template and styles properties of a component // Our transformers will be executed at the end, at this point, the original "templateUrl" and // "styleUrls" keys have been renamed to the following ones by the replace_sources transformer // located in @ngtools/webpack/src/transformers/replace_sources const templateKey = 'template'; const stylesKey = 'styles'; const templateKeys = ['templateUrl', 'template']; const stylesKeys = ['styles', 'styleUrls']; const filterKeys = templateKeys.concat(stylesKeys); function createCLMetadataTransform(shouldTransform) { const standardTransform = function (sourceFile) { const ops = []; if (!shouldTransform(sourceFile.fileName)) { return ops; } const styleUrls = []; let templateUrl = null; ast_helpers_1.collectDeepNodes(sourceFile, ts.SyntaxKind.ObjectLiteralExpression) .map(function (node) { return ast_helpers_1.collectDeepNodes(node, ts.SyntaxKind.PropertyAssignment) }) .reduce(function (prev, curr) { return curr ? prev.concat(curr) : prev; }, []) .filter(function (node) { const key = _getContentOfKeyLiteral(sourceFile, node.name); if (!key) { return false; } return filterKeys.indexOf(key) !== -1; }) .forEach(function (node) { let key = _getContentOfKeyLiteral(sourceFile, node.name); if (templateKeys.indexOf(key) !== -1) { let templateUrlNode = ast_helpers_1.collectDeepNodes(node, ts.SyntaxKind.StringLiteral); if (!templateUrlNode || !templateUrlNode.length || !templateUrlNode[0].text) { return; } // [bug 32723] let templateUrlNodeText = templateUrlNode.length === 1 ? templateUrlNode[0].text : path.basename(templateUrlNode[1].text) templateUrl = path.normalize( path.join( path.dirname(sourceFile.fileName), templateUrlNodeText.replace('!raw-loader!', '') ) ); } else if (stylesKeys.indexOf(key) !== -1) { const arr = (ast_helpers_1.collectDeepNodes(node, ts.SyntaxKind.ArrayLiteralExpression)); if (!arr || arr.length === 0 || arr[0].elements.length === 0) { return; } arr[0].elements.forEach(function (arrElement) { // This strategy works on 1.5.0 if (arrElement.arguments) { arrElement.arguments.forEach(function (argument) { const dirName = path.dirname(sourceFile.fileName); let styleUrl = path.normalize(path.join(dirName, argument.text)); if (styleUrl) styleUrls.push(styleUrl); }); // This strategy works for pre 1.5.0 (e.g. 1.5.0-rc.8) } else { const dirName = path.dirname(sourceFile.fileName); let styleUrlPath; if (arrElement.text) { styleUrlPath = arrElement.text; } // Adds support for Angular CLI 8.3.2 >= if ( styleUrlPath === undefined && arrElement.expression && arrElement.expression.arguments && arrElement.expression.arguments.length > 0 && arrElement.expression.arguments[0].arguments && arrElement.expression.arguments[0].arguments.length > 0 && arrElement.expression.arguments[0].arguments[0].text) { styleUrlPath = arrElement.expression.arguments[0].arguments[0].text; } if (styleUrlPath) { const styleUrl = path.normalize(path.join(dirName, styleUrlPath)); styleUrls.push(styleUrl); } } }); } }); let isAComponent = false; if (sourceFile.identifiers) { if (typeof sourceFile.identifiers.Component !== 'undefined') { isAComponent = true; } if (!isAComponent && typeof sourceFile.identifiers.get === 'function') { isAComponent = sourceFile.identifiers.get('Component') } } if (isAComponent) { ast_helpers_1.collectDeepNodes(sourceFile, ts.SyntaxKind.ClassDeclaration) .forEach(function (node) { let tsPath = path.normalize(sourceFile.fileName); const metadataToInject = { componentPath: tsPath, styleUrls: styleUrls, }; if (templateUrl !== null && fs.existsSync(templateUrl)) { metadataToInject.templateUrl = templateUrl; } const newProperties = Object.keys(metadataToInject).map((key) => { return ts.createPropertyAssignment(ts.createLiteral(key), convertValueToLiteral(metadataToInject[key])); }); const metadataProperty = ts.createProperty( undefined, [ts.createToken(ts.SyntaxKind.PublicKeyword)], '__clMeta', undefined, undefined, ts.createObjectLiteral(newProperties) ); // Check if if there is already a cl metadata node let clMetaNode = node.members.find(memberNode => { // Note that the '__clMeta' escaped version has and extra lodash if (memberNode.name && memberNode.name.escapedText) { return memberNode.name.escapedText === '___clMeta'; } else { return false; } }); let members = []; // If there is a metadata node, just replace it, otherwise add to the members list if (clMetaNode) { clMetaNode = metadataProperty; members = node.members; } else { members = node.members.concat(metadataProperty) } const updatedClassDeclarationNode = ts.updateClassDeclaration( node, node.decorators, node.modifiers, node.name, node.typeParameters, node.heritageClauses, members ); ops.push(new interfaces_1.ReplaceNodeOperation(sourceFile, node, updatedClassDeclarationNode)); }); } return ops; } return make_transform_1.makeTransform(standardTransform); } let AngularCompilerPluginModule = null; AngularCompilerPluginModule = require(`${ngtoolsPath}/webpack/src/angular_compiler_plugin`); require.cache['@ngtools/webpack/src/angular_compiler_plugin'] = require(`${ngtoolsPath}/webpack/src/angular_compiler_plugin`); let manifest = null; manifest = require(`${ngtoolsPath}/webpack/package.json`) ngToolsPKGVersion = manifest.version; if (semver.satisfies(ngToolsPKGVersion, '<1.8.0-a')) { return; } AngularCompilerPluginModule.AngularCompilerPlugin.prototype.originalEmit = AngularCompilerPluginModule.AngularCompilerPlugin.prototype._emit; AngularCompilerPluginModule.AngularCompilerPlugin.prototype._emit = function (sourceFiles) { const transformOps = []; const self = this; const isAppPath = (fileName) => !fileName.endsWith('.ngfactory.ts') && !fileName.endsWith('.ngstyle.ts'); this._transformers.push(createCLMetadataTransform(isAppPath)); return this.originalEmit(sourceFiles); }; } } function injectComponentMetadata_4() { // Importing ngtools transformation helpers const make_transform_1 = require("@ngtools/webpack/src/transformers/make_transform"); const ast_helpers_1 = require("@ngtools/webpack/src/transformers/ast_helpers"); function createCLMetadataTransform(sourceFile) { const ops = []; const styleUrls = []; let templateUrl = null; ast_helpers_1.findAstNodes(null, sourceFile, ts.SyntaxKind.ObjectLiteralExpression, true) .map(function (node) { return ast_helpers_1.findAstNodes(node, sourceFile, ts.SyntaxKind.PropertyAssignment) }) .reduce(function (prev, curr) { return curr ? prev.concat(curr) : prev; }, []) .filter(function (node) { const key = _getContentOfKeyLiteral(sourceFile, node.name); if (!key) { // key is an expression, can't do anything. return false; } return key == 'templateUrl' || key == 'styleUrls'; }) .forEach(function (node) { let key = _getContentOfKeyLiteral(sourceFile, node.name); if (key == 'templateUrl') { let templateUrlNode = ast_helpers_1.findAstNodes(node, sourceFile, ts.SyntaxKind.StringLiteral, true); if (!templateUrlNode || !templateUrlNode.length || !templateUrlNode[0].text) { return; } templateUrl = path.normalize(path.join( path.dirname(sourceFile.fileName), templateUrlNode[0].text )); } else if (key == 'styleUrls') { const arr = (ast_helpers_1.findAstNodes(node, sourceFile, ts.SyntaxKind.ArrayLiteralExpression, false)); if (!arr || arr.length == 0 || arr[0].elements.length == 0) { return; } arr.forEach(function (arrElement) { const dirName = path.dirname(sourceFile.fileName); let styleUrl = path.normalize(path.join(dirName, arrElement.elements[0].text)); styleUrls.push(styleUrl); }); const initializer = arr[0].elements.map(function (element) { return element.getFullText(sourceFile); }); } }); let isAComponent = false; if (sourceFile.identifiers) { if (typeof sourceFile.identifiers.Component !== 'undefined') { isAComponent = true; } if (!isAComponent && typeof sourceFile.identifiers.get === 'function') { isAComponent = sourceFile.identifiers.get('Component') } } if (isAComponent) { ast_helpers_1.findAstNodes(null, sourceFile, ts.SyntaxKind.ClassDeclaration, true) .forEach(function (node) { let tsPath = path.normalize(sourceFile.fileName); const metadataToInject = { componentPath: tsPath, styleUrls: styleUrls, }; if (templateUrl !== null && fs.existsSync(templateUrl)) { metadataToInject.templateUrl = templateUrl; } const newProperties = Object.keys(metadataToInject).map((key) => { return ts.createPropertyAssignment(ts.createLiteral(key), convertValueToLiteral(metadataToInject[key])); }); const metadataProperty = ts.createProperty( undefined, [ts.createToken(ts.SyntaxKind.PublicKeyword)], '__clMeta', undefined, undefined, ts.createObjectLiteral(newProperties) ); // Check if if there is already a cl metadata node let clMetaNode = node.members.find(memberNode => { // Note that the '__clMeta' escaped version has and extra lodash if (memberNode.name && memberNode.name.escapedText) { return memberNode.name.escapedText === '___clMeta'; } else { return false; } }); let members = []; // If there is a metadata node, just replace it, otherwise add to the members list if (clMetaNode) { clMetaNode = metadataProperty; members = node.members; } else { members = node.members.concat(metadataProperty) } const updatedClassDeclarationNode = ts.updateClassDeclaration( node, node.decorators, node.modifiers, node.name, node.typeParameters, node.heritageClauses, members ); ops.push(new make_transform_1.ReplaceNodeOperation(sourceFile, node, updatedClassDeclarationNode)); }); } return ops; } let AngularCompilerPluginModule = null; try { AngularCompilerPluginModule = require('@ngtools/webpack/src/angular_compiler_plugin'); } catch (e) { AngularCompilerPluginModule = require('@angular/cli/node_modules/@ngtools/webpack/src/angular_compiler_plugin'); require.cache['@ngtools/webpack/src/angular_compiler_plugin'] = require('@angular/cli/node_modules/@ngtools/webpack/src/angular_compiler_plugin'); } let manifest = null; try { manifest = require('@ngtools/webpack/package.json') } catch (e) { manifest = require('@angular/cli/node_modules/@ngtools/webpack/package.json') } ngToolsPKGVersion = manifest.version; if (semver.satisfies(ngToolsPKGVersion, '<1.8.0-a')) { return; } AngularCompilerPluginModule.AngularCompilerPlugin.prototype.originalEmit = AngularCompilerPluginModule.AngularCompilerPlugin.prototype._emit; AngularCompilerPluginModule.AngularCompilerPlugin.prototype._emit = function (sourceFiles, customTransformers) { const transformOps = []; sourceFiles.forEach(function createCLMetadaTransform(sf) { transformOps.push(...createCLMetadataTransform(sf)); }); customTransformers.beforeTs.push(make_transform_1.makeTransform(transformOps)); return this.originalEmit(sourceFiles, customTransformers); }; } function injectCLBootstrapScript_1(ngCLIVersion, config) { const NgCliWebpackConfig = require(`${ngCLIPath}/models/webpack-config`).NgCliWebpackConfig; NgCliWebpackConfig.prototype.originalGetTargetConfig1 = NgCliWebpackConfig.prototype.getTargetConfig; NgCliWebpackConfig.prototype.getTargetConfig = function monkeyPatchedGenerateConfig(projectRoot, appConfig) { const targetConfig = this.originalGetTargetConfig1(projectRoot, appConfig); if (typeof targetConfig.module === 'undefined') { targetConfig.module = { rules: [] }; } if (typeof targetConfig.module.rules === 'undefined') { targetConfig.module.rules = []; } targetConfig.module.rules.push({ test: /\.(html)$/, loader: 'angular-ide-loader', options: config }); return targetConfig; }; } function injectCLBootstrapScript_2(ngCLIVersion, config) { const NgCliWebpackConfig = require(`${ngCLIPath}/models/webpack-config`).NgCliWebpackConfig; NgCliWebpackConfig.prototype.originalGetTargetConfig = NgCliWebpackConfig.prototype.getTargetConfig; NgCliWebpackConfig.prototype.getTargetConfig = function monkeyPatchedGenerateConfig(projectRoot, appConfig) { const targetConfig = this.originalGetTargetConfig(projectRoot, appConfig); (function () { if (typeof targetConfig.plugins === 'undefined') { targetConfig.plugins = []; } targetConfig.plugins.push(new CLBootstrapInjectorPlugin(config)); })(); return targetConfig; }; } function injectComponentMetadata(ngCLIVersion) { if (semver.satisfies(ngCLIVersion, '>=1.0.0-beta.16 <1.0.0-beta.22')) { injectComponentMetadata_2(); return; } const possibleNGToolsModulePaths = [ '', '@angular/cli/node_modules/', '@angular-devkit/build-angular/node_modules/', ]; let ngtoolsPath = possibleNGToolsModulePaths.find((possiblePath) => { const resolvedPath = path.resolve(__dirname, '../../', possiblePath, '@ngtools'); return fs.existsSync(resolvedPath); }); if (ngtoolsPath !== false) { ngtoolsPath += '@ngtools'; } else { throw new Error('@ngtools was not found'); } // Determining the next injection strategy const manifest = require(`${ngtoolsPath}/webpack/package.json`) ngToolsPKGVersion = manifest.version; if (semver.satisfies(ngToolsPKGVersion, '<1.8.0-a')) { // Strategy for pre Angular 5 injectComponentMetadata_1(); } else { // Extracting simple version const majorVersion = semver.major(ngCLIVersion); const minorVersion = semver.minor(ngCLIVersion); const patchVersion = semver.patch(ngCLIVersion); const simpleVersion = `${majorVersion}.${minorVersion}.${patchVersion}`; // Strategy for Angular 5 if ( semver.satisfies(ngCLIVersion, '>=1.5.0-rc.8') || semver.satisfies(ngCLIVersion, '>=1.5.0') || semver.satisfies(simpleVersion, '>=1.6.0') ) { if (CLEnablementStatusManager.getStatus()) { injectComponentMetadata_3(ngtoolsPath); } } else { injectComponentMetadata_4(); } } } function injectCLBootstrapScript(ngCLIVersion, config) { if (semver.satisfies(ngCLIVersion, '>=1.0.0-beta.16 <1.0.0-beta.25')) { injectCLBootstrapScript_1(ngCLIVersion, config); return; } if (semver.satisfies(semver.coerce(ngCLIVersion), '>=6.0.0')) { injectCLBootstrapScript_3(ngCLIVersion, config); return; } injectCLBootstrapScript_2(ngCLIVersion, config); } function injectCLBootstrapScript_3(ngCLIVersion, config) { let htmlPlugin; try { htmlPlugin = require('../../@angular-devkit/build-angular/src/angular-cli-files/plugins/index-html-webpack-plugin'); require.cache['@angular-devkit/build-angular/src/angular-cli-files/plugins/index-html-webpack-plugin'] = require('../../@angular-devkit/build-angular/src/angular-cli-files/plugins/index-html-webpack-plugin'); } catch { htmlPlugin = require('../../@angular-devkit/build-angular/src/webpack/plugins/index-html-webpack-plugin'); require.cache['@angular-devkit/build-angular/src/webpack/plugins/index-html-webpack-plugin'] = require('../../@angular-devkit/build-angular/src/webpack/plugins/index-html-webpack-plugin'); } try { const webpack = require('webpack'); let patchedClass; if (semver.satisfies(webpack.version, '>=5.x')) { patchedClass = class PatchedIndexHTMLWebpackPlugin extends htmlPlugin.IndexHtmlWebpackPlugin { apply(compiler) { super.apply(compiler); compiler.hooks.thisCompilation.tap('index-html-webpack-plugin', (compilation) => { // Static Plugin interface |compilation |HOOK NAME | register listener compilation .hooks.processAssets.tapPromise({ name: 'index-html-webpack-plugin', stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE + 2, },(assets) => { return new Promise((resolve, reject) => { if (CLEnablementStatusManager.getStatus()) { let outputKey; if (this.options) { outputKey = this.options.outputPath; } else { outputKey = this._options.output; } const patchedContents = assets[outputKey].source() .replace('</body>', `<script>window._CLPort = ${config.port};</script><script src="http://${config.host}:${config.port}/ngcl/ngcl-assets/bundle.js"></script></body>`); assets[outputKey] = { source: function () { return patchedContents; }, size: function () { return patchedContents.length; } }; } resolve(); }) }) }); } } } else { patchedClass = class PatchedIndexHTMLWebpackPlugin extends htmlPlugin.IndexHtmlWebpackPlugin { apply(compiler) { super.apply(compiler); compiler.hooks.emit.tapPromise('index-html-webpack-plugin', (compilation) => { return new Promise((resolve, reject) => { if (CLEnablementStatusManager.getStatus()) { let outputKey; if (this.options) { outputKey = this.options.outputPath; } else { outputKey = this._options.output; } const patchedContents = compilation.assets[outputKey].source() .replace('</body>', `<script>window._CLPort = ${config.port};</script><script src="http://${config.host}:${config.port}/ngcl/ngcl-assets/bundle.js"></script></body>`); compilation.assets[outputKey] = { source: function () { return patchedContents; }, size: function () { return patchedContents.length; } }; } resolve(); }); }); } } } htmlPlugin.IndexHtmlWebpackPlugin = patchedClass; } catch (e) { debug(chalk.red('Unable to patch IndexHtmlWebpackPlugin')); throw e; } } function normalizePackageVersion(packageVersion) { return packageVersion.replace(/-(rc|beta).(\d*)/, ''); } function getNGCLIManifest() { let manifest = null; try { manifest = require('../../@angular/cli/package.json') } catch (e) { debug('Unable to detect package using new name, trying with old name'); } if (manifest === null) { try { manifest = require('../../angular-cli/package.json'); } catch (e) { debug(chalk.red('Unable to detect package using old name')); } } return manifest; } function getNGCLIPath(packageName) { let rootPath = null; switch (packageName) { case 'angular-cli': rootPath = 'angular-cli'; break; case '@angular/cli': rootPath = '@angular/cli'; break; default: } return rootPath; } module.exports.injectComponentMetadata = injectComponentMetadata; module.exports.injectCLBootstrapScript = injectCLBootstrapScript; module.exports.normalizePackageVersion = normalizePackageVersion; module.exports.getNGCLIManifest = getNGCLIManifest; module.exports.getNGCLIPath = getNGCLIPath;