blob: 0dc4ff848fff0be0b94d7ca0094876d9e67bc1c6 [file] [log] [blame]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var async = require("async");
var fs = require("fs");
var lodash = require("lodash");
var path = require("path");
var tmp = require("tmp");
var benchmark_1 = require("../shared/benchmark");
var PathTool = require("../shared/path-tool");
var bundle_item_1 = require("./bundle-item");
require("../client/commonjs");
var Bundler = /** @class */ (function () {
function Bundler(config, dependencyWalker, globals, log, project, resolver, sourceMap, transformer, validator) {
this.config = config;
this.dependencyWalker = dependencyWalker;
this.globals = globals;
this.log = log;
this.project = project;
this.resolver = resolver;
this.sourceMap = sourceMap;
this.transformer = transformer;
this.validator = validator;
this.BUNDLE_DELAY = 500;
this.bundleQueuedModulesDeferred = lodash.debounce(this.bundleQueuedModules, this.BUNDLE_DELAY);
this.bundleBuffer = [];
this.bundleFile = tmp.fileSync({
postfix: ".js",
prefix: "karma-typescript-bundle-"
});
this.bundleQueue = [];
this.entrypoints = [];
this.projectImportCountOnFirstRun = undefined;
}
Bundler.prototype.attach = function (files) {
files.unshift({
included: true,
pattern: this.bundleFile.name,
served: true,
watched: true
});
files.push({
included: true,
pattern: path.join(__dirname, "../../dist/client/commonjs.js"),
served: true,
watched: false
});
};
Bundler.prototype.bundle = function (file, emitOutput, callback) {
this.bundleQueue.push({ callback: callback, emitOutput: emitOutput, file: file });
this.bundleQueuedModulesDeferred();
};
Bundler.prototype.bundleQueuedModules = function () {
var _this = this;
// Drain the bundle queue and keep a copy of the current items. This prevents problems
// when a new bundle is queued while transformations are running.
var queuedItems = this.bundleQueue.slice(0);
this.bundleQueue.length = 0;
var benchmark = new benchmark_1.Benchmark();
this.transformer.applyTsTransforms(queuedItems, function () {
queuedItems.forEach(function (queued) {
var source = _this.sourceMap.removeSourceMapComment(queued);
var map = _this.sourceMap.getSourceMap(queued);
if (map) {
// used by Karma to log errors with original source code line numbers
queued.file.sourceMap = map.toObject();
}
queued.item = new bundle_item_1.BundleItem(queued.file.path, queued.file.originalPath, source, map);
});
var dependencyCount = _this.dependencyWalker.collectTypescriptDependencies(queuedItems);
if (_this.shouldBundle(dependencyCount)) {
_this.bundleWithLoader(benchmark, queuedItems);
}
else {
_this.bundleWithoutLoader(queuedItems);
}
});
};
Bundler.prototype.shouldBundle = function (dependencyCount) {
if (this.config.hasPreprocessor("commonjs")) {
this.log.debug("Preprocessor 'commonjs' detected, code will NOT be bundled");
return false;
}
if (!this.project.hasCompatibleModuleKind()) {
this.log.debug("Module kind set to '%s', code will NOT be bundled", this.project.getModuleKind());
return false;
}
if (this.projectImportCountOnFirstRun === undefined) {
this.projectImportCountOnFirstRun = dependencyCount;
}
this.log.debug("Project has %s import/require statements, code will be%sbundled", this.projectImportCountOnFirstRun, this.projectImportCountOnFirstRun > 0 ? " " : " NOT ");
return this.projectImportCountOnFirstRun > 0;
};
Bundler.prototype.bundleWithLoader = function (benchmark, queuedItems) {
var _this = this;
async.each(queuedItems, function (queued, onQueuedResolved) {
_this.addEntrypointFilename(queued.item.filename);
async.each(queued.item.dependencies, function (bundleItem, onDependencyResolved) {
_this.resolver.resolveModule(queued.item.moduleName, bundleItem, _this.bundleBuffer, function () {
onDependencyResolved();
});
}, onQueuedResolved);
}, function () {
_this.onAllResolved(benchmark, queuedItems);
});
};
Bundler.prototype.bundleWithoutLoader = function (queuedItems) {
var _this = this;
this.globals.add(this.bundleBuffer, this.entrypoints, function () {
_this.writeMainBundleFile(function () {
queuedItems.forEach(function (queued) {
var source = queued.item.source + "\n" +
(queued.item.sourceMap ? queued.item.sourceMap.toComment() + "\n" : "");
queued.callback(source);
});
});
});
};
Bundler.prototype.onAllResolved = function (benchmark, queuedItems) {
var _this = this;
this.orderEntrypoints();
this.globals.add(this.bundleBuffer, this.entrypoints, function () {
_this.writeMainBundleFile(function () {
_this.log.info("Bundled imports for %s file(s) in %s ms.", queuedItems.length, benchmark.elapsed());
queuedItems.forEach(function (queued) {
queued.callback(_this.addLoaderFunction(queued.item, true));
});
_this.log.debug("Karma callbacks for %s file(s) in %s ms.", queuedItems.length, benchmark.elapsed());
});
});
};
Bundler.prototype.addLoaderFunction = function (bundleItem, standalone) {
var _this = this;
var dependencyMap = {};
var moduleId = path.relative(this.config.karma.basePath, bundleItem.filename);
bundleItem.dependencies.forEach(function (dependency) {
if (!dependency.filename) {
_this.log.debug("No resolved filename for module [%s], required by [%s]", dependency.moduleName, bundleItem.filename);
}
else {
dependencyMap[dependency.moduleName] = PathTool.fixWindowsPath(dependency.filename);
}
});
return (standalone ? "(function(global){" : "") +
"global.wrappers['" + PathTool.fixWindowsPath(bundleItem.filename) + "']=" +
"[function(require,module,exports,__dirname,__filename){ " + bundleItem.source +
"\n},'" +
PathTool.fixWindowsPath(moduleId) + "'," +
PathTool.fixWindowsPath(JSON.stringify(dependencyMap)) + "];" +
(standalone ? "})(this);" : "") + "\n" +
(bundleItem.sourceMap ? bundleItem.sourceMap.toComment() + "\n" : "");
};
Bundler.prototype.createEntrypointFilenames = function () {
if (this.entrypoints.length > 0) {
return "global.entrypointFilenames=['" + this.entrypoints.join("','") + "'];\n";
}
return "";
};
Bundler.prototype.addEntrypointFilename = function (filename) {
if (this.config.bundlerOptions.entrypoints.test(filename) &&
this.entrypoints.indexOf(filename) === -1) {
this.entrypoints.push(filename);
}
};
Bundler.prototype.orderEntrypoints = function () {
var _this = this;
var orderedEntrypoints = [];
this.project.getKarmaFiles().forEach(function (filename) {
if (_this.entrypoints.indexOf(filename) !== -1) {
orderedEntrypoints.push(filename);
}
});
this.entrypoints = orderedEntrypoints;
};
Bundler.prototype.writeMainBundleFile = function (onMainBundleFileWritten) {
var _this = this;
var bundle = "(function(global){\nglobal.wrappers={};\n";
this.sourceMap.initialize(bundle);
this.bundleBuffer.forEach(function (bundleItem) {
_this.sourceMap.addFile(bundleItem);
var wrapped = _this.addLoaderFunction(bundleItem, false);
bundle += wrapped;
_this.sourceMap.offsetLineNumber(wrapped);
});
bundle += this.createEntrypointFilenames() + "})(this);\n";
bundle += this.sourceMap.getComment();
this.validator.validate(bundle, this.bundleFile.name);
fs.writeFile(this.bundleFile.name, bundle, function (error) {
if (error) {
throw error;
}
onMainBundleFileWritten();
});
};
return Bundler;
}());
exports.Bundler = Bundler;
//# sourceMappingURL=bundler.js.map