| "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 |