angular-cli/lib/broccoli/angular2-app.js
Igor Minar 19774b9898 fix(build): compile source files from within the src/ directory
We need to preserve the paths to be the same during build as they are in source repo,
so that editor and build pipeline are aligned.
2016-03-17 16:23:54 -07:00

251 lines
6.5 KiB
JavaScript

var path = require('path');
var Concat = require('broccoli-concat');
var configReplace = require('./broccoli-config-replace');
var compileWithTypescript = require('./broccoli-typescript').default;
var SwManifest = require('./service-worker-manifest').default;
var fs = require('fs');
var Funnel = require('broccoli-funnel');
var mergeTrees = require('broccoli-merge-trees');
var Project = require('ember-cli/lib/models/project');
module.exports = Angular2App;
function Angular2App(defaults, options, additionalPaths) {
this._initProject();
this._notifyAddonIncluded();
this.options = options;
this.additionalPaths = additionalPaths || [];
}
Angular2App.prototype.toTree = function() {
var sourceDir = 'src';
var sourceTree = new Funnel('src', {
destDir: 'src'
});
var typingsTree = new Funnel('typings', {
include: ['browser.d.ts', 'browser/**'],
destDir: 'typings'
});
var vendorNpmFiles = [
'systemjs/dist/system-polyfills.js',
'systemjs/dist/system.src.js',
'es6-shim/es6-shim.js',
'angular2/bundles/angular2-polyfills.js',
'rxjs/bundles/Rx.js',
'angular2/bundles/angular2.dev.js',
'angular2/bundles/http.dev.js',
'angular2/bundles/router.dev.js',
'angular2/bundles/upgrade.dev.js'
];
if (this.options && this.options.vendorNpmFiles) {
vendorNpmFiles = vendorNpmFiles.concat(this.options.vendorNpmFiles);
}
var tsconfig = JSON.parse(fs.readFileSync('src/tsconfig.json', 'utf-8'));
var tsConfigCompilerOptions = tsconfig.compilerOptions;
// TODO(i): why do we need these additional paths? remove?
tsConfigCompilerOptions.rootFilePaths = this.additionalPaths.map(function(name) {
return path.join(process.cwd(), sourceDir, name)
});
// TODO(i): kill rootFilePaths in broccoli-typescript and use tsconfig.json#files instead
tsConfigCompilerOptions.rootFilePaths = tsConfigCompilerOptions.rootFilePaths.
concat(tsconfig.files.map(function(p) {
// TODO(i): this is a hack - for some reason we need to prefix all paths with srcDir because
// tsc's "rootDir" doesn't take effect when resolving "files" paths
return path.join(sourceDir, p);
}));
var srcAndTypingsTree = mergeTrees([sourceTree, typingsTree]);
var tsTree = compileWithTypescript(srcAndTypingsTree, tsConfigCompilerOptions);
tsTree = new Funnel(tsTree, {
srcDir: 'src',
exclude: ['*.d.ts', 'tsconfig.json']
});
var tsSrcTree = new Funnel(sourceDir, {
include: ['**/*.ts'],
allowEmpty: true
});
var jsTree = new Funnel(sourceDir, {
include: ['**/*.js'],
allowEmpty: true
});
var assetTree = new Funnel(sourceDir, {
include: ['**/*.*'],
exclude: ['**/*.ts', '**/*.js'],
allowEmpty: true
});
var vendorNpmTree = new Funnel('node_modules', {
include: vendorNpmFiles,
destDir: 'vendor'
});
var thirdPartyJsTree = new Funnel('node_modules', {
include: ['ng2*/bundles/*.js'],
exclude: ['ng2*/bundles/*.min.js', 'ng2*/bundles/*.standalone.js'],
});
var thirdPartyJs = new Concat(thirdPartyJsTree, {
inputFiles: ['**/*.js'],
outputFile: '/thirdparty/libs.js',
allowNone: true
});
var merged = mergeTrees([
assetTree,
tsSrcTree,
tsTree,
jsTree,
this.index(),
vendorNpmTree,
thirdPartyJs
], { overwrite: true });
return mergeTrees([merged, new SwManifest(merged)]);
};
/**
@private
@method _initProject
@param {Object} options
*/
Angular2App.prototype._initProject = function() {
this.project = Project.closestSync(process.cwd());
/*if (options.configPath) {
this.project.configPath = function() { return options.configPath; };
}*/
};
/**
@private
@method _notifyAddonIncluded
*/
Angular2App.prototype._notifyAddonIncluded = function() {
this.initializeAddons();
this.project.addons = this.project.addons.filter(function(addon) {
addon.app = this;
if (!addon.isEnabled || addon.isEnabled()) {
if (addon.included) {
addon.included(this);
}
return addon;
}
}, this);
};
/**
Loads and initializes addons for this project.
Calls initializeAddons on the Project.
@private
@method initializeAddons
*/
Angular2App.prototype.initializeAddons = function() {
this.project.initializeAddons();
};
/**
Returns the content for a specific type (section) for index.html.
Currently supported types:
- 'head'
//- 'config-module'
//- 'app'
//- 'head-footer'
//- 'test-header-footer'
//- 'body-footer'
//- 'test-body-footer'
Addons can also implement this method and could also define additional
types (eg. 'some-addon-section').
@private
@method contentFor
@param {RegExP} match Regular expression to match against
@param {String} type Type of content
@return {String} The content.
*/
Angular2App.prototype.contentFor = function(match, type) {
var content = [];
/*switch (type) {
case 'head': this._contentForHead(content, config); break;
case 'config-module': this._contentForConfigModule(content, config); break;
case 'app-boot': this._contentForAppBoot(content, config); break;
}*/
content = this.project.addons.reduce(function(content, addon) {
var addonContent = addon.contentFor ? addon.contentFor(type) : null;
if (addonContent) {
return content.concat(addonContent);
}
return content;
}, content);
return content.join('\n');
};
/**
@private
@method _configReplacePatterns
@return
*/
Angular2App.prototype._configReplacePatterns = function() {
return [/*{
match: /\{\{EMBER_ENV\}\}/g,
replacement: calculateEmberENV
}, */{
match: /\{\{content-for ['"](.+)["']\}\}/g,
replacement: this.contentFor.bind(this)
}/*, {
match: /\{\{MODULE_PREFIX\}\}/g,
replacement: calculateModulePrefix
}*/];
};
/**
Returns the tree for app/index.html
@private
@method index
@return {Tree} Tree for app/index.html
*/
Angular2App.prototype.index = function() {
var htmlName = 'index.html';
var files = [
'index.html'
];
var index = new Funnel('src', {
files: files,
description: 'Funnel: index.html'
});
return configReplace(index, {
files: [ htmlName ],
patterns: this._configReplacePatterns()
});
};