From a82f1fb3c0714cfc3652657c7dfada474350182a Mon Sep 17 00:00:00 2001 From: eggyal Date: Thu, 28 May 2015 21:14:12 +0100 Subject: [PATCH 01/13] Fixes atomify/atomify-js#62 Fixes --- index.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 6c54b53..ac9a7eb 100644 --- a/index.js +++ b/index.js @@ -34,7 +34,6 @@ ctor = module.exports = function atomifyJs (opts, cb) { , assets , outputs , b - , w if (Array.isArray(opts)) opts = {entries: opts} if (typeof opts === 'string') opts = {entries: [opts]} @@ -104,20 +103,20 @@ ctor = module.exports = function atomifyJs (opts, cb) { emitter.emit('browserify', b) if (opts.watch) { - w = watchify(b) - emitter.emit('watchify', w) + b = watchify(b) + emitter.emit('watchify', b) } if (opts.watch) { - w.on('update', function onUpdate (ids) { + b.on('update', function onUpdate (ids) { ids.forEach(function eachId (id) { emitter.emit('changed', id) }) - w.bundle(cb) + rebundle() }) - w.on('time', function onTime (time) { + b.on('time', function onTime (time) { emitter.emit('bundle', time) }) } @@ -199,6 +198,9 @@ ctor = module.exports = function atomifyJs (opts, cb) { b.external(opts.external) } + return rebundle() + + function rebundle() { // if we've got the common option, we want to use factor bundle if (opts.common === true){ if (opts.entries.length < 2) { @@ -250,6 +252,7 @@ ctor = module.exports = function atomifyJs (opts, cb) { } // if we don't need to use factor bundle, just browserify! else return b.bundle(cb) + } } ctor.emitter = emitter From d3e2f60a078536a2c7355c6b1aade54830782125 Mon Sep 17 00:00:00 2001 From: Joey Baker Date: Fri, 29 May 2015 15:25:19 -0700 Subject: [PATCH 02/13] internal: linter #cleanup --- test/watch.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/watch.js b/test/watch.js index de09ce9..9ce15fd 100644 --- a/test/watch.js +++ b/test/watch.js @@ -9,14 +9,14 @@ var test = require('tape') , changerPath = path.join(outputPath, 'changer.js') , now = Date.now() , mkdirp = require('mkdirp') - , setup = function setup(){ + , setup = function setup () { var file = 'module.exports = ' + now mkdirp.sync(outputPath) fs.writeFileSync(changerPath, file) } -test('opts.watch', function(t){ +test('opts.watch', function (t) { var callbackCallCount = 0 , callback , w @@ -24,12 +24,12 @@ test('opts.watch', function(t){ setup() // get the watchify instance so that we can close it an end the test - lib.emitter.once('watchify', function assignWatchify(watchify){ + lib.emitter.once('watchify', function assignWatchify (watchify) { w = watchify }) // callback will be called each time the changer file is changed - callback = function callback(err, bundle){ + callback = function callback (err, bundle) { var src = bundle.toString() , changerContents2 = 'module.exports = changed' @@ -66,7 +66,7 @@ test('opts.watch', function(t){ // run the lib with watchify enabled // wait just a bit to ensure all the file watchers are in place - setTimeout(function(){ + setTimeout(function () { lib({watch: true, entry: path.join(entryPath, 'index.js')}, callback) }, 50) }) From 0720277e6f8ad3061224d1688f7d33064cd4ee25 Mon Sep 17 00:00:00 2001 From: Joey Baker Date: Fri, 29 May 2015 15:25:33 -0700 Subject: [PATCH 03/13] internal: fix watch test not finishing --- test/watch.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/watch.js b/test/watch.js index 9ce15fd..8d7490d 100644 --- a/test/watch.js +++ b/test/watch.js @@ -44,8 +44,11 @@ test('opts.watch', function (t) { , 'contains the watched dep on inital callback' ) - // commit a change to the file so that we trigger the callback again - fs.writeFile(changerPath, changerContents2) + // wait for a bit to write the file because watchify has a delay + setTimeout(function () { + // commit a change to the file so that we trigger the callback again + fs.writeFile(changerPath, changerContents2) + }, 600) } else { // close all file handlers ← important so that tests exit From 855dabce1b6a5367d789ed9fe5fa07cb5454ded6 Mon Sep 17 00:00:00 2001 From: Joey Baker Date: Fri, 29 May 2015 15:26:42 -0700 Subject: [PATCH 04/13] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a5b68c..df1f744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 4.7.2 +* fix: directly require factor-bundle. #61 +* internal: fix watch test not finishing + ## 4.7.1 * internal: linter cleanup From e4a7a94d0daaa682a563be9cf3b8540dbdb108e8 Mon Sep 17 00:00:00 2001 From: Joey Baker Date: Fri, 29 May 2015 15:26:50 -0700 Subject: [PATCH 05/13] 4.7.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5aadaee..24ccb4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "atomify-js", - "version": "4.7.1", + "version": "4.7.2", "description": "Atomic JavaScript - Reusable front-end modules using Browserify, transforms, and templates", "main": "index.js", "scripts": { From 56bce9f58ef62183e9bcc1fc1227d914abc2c098 Mon Sep 17 00:00:00 2001 From: Joey Baker Date: Fri, 29 May 2015 15:27:53 -0700 Subject: [PATCH 06/13] =?UTF-8?q?internal:=20add=20more=20delay=20to=20wat?= =?UTF-8?q?ch=20test=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit prevents intermittent failures. --- test/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/watch.js b/test/watch.js index 8d7490d..a059e34 100644 --- a/test/watch.js +++ b/test/watch.js @@ -48,7 +48,7 @@ test('opts.watch', function (t) { setTimeout(function () { // commit a change to the file so that we trigger the callback again fs.writeFile(changerPath, changerContents2) - }, 600) + }, 800) } else { // close all file handlers ← important so that tests exit From 52cd9b081901999ac9147d6a3209ae2ad9747a55 Mon Sep 17 00:00:00 2001 From: eggyal Date: Fri, 29 May 2015 10:23:14 +0100 Subject: [PATCH 07/13] Ensures factor bundle correctly matches entries to output streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation for [`_.values(object)`](https://lodash.com/docs#values) gives an example: > _.values(new Foo); > // → [1, 2] (iteration order is not guaranteed) Since "iteration order is not guaranteed", the array of streams passed to factor-bundle may not be in the same order as the corresponding files in `entries`. Factor bundle [depends on this correlation](https://github.com/substack/factor-bundle/blob/master/index.js#L73) when building its pipeline. This commit ensures that there is never a mismatch. --- index.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index ac9a7eb..64d9574 100644 --- a/index.js +++ b/index.js @@ -210,20 +210,20 @@ ctor = module.exports = function atomifyJs (opts, cb) { } // for each entry, we're going to create a stream-able buffer to put the factored bundle into - outputs = {} + outputs = [] opts.entries.forEach(function createOutputs (entry) { - outputs[path.basename(entry).replace(path.extname(entry), '')] = new streamBuffer.WritableStreamBuffer({ + outputs.push(new streamBuffer.WritableStreamBuffer({ // these values are arbitrary, but we don't want to require huge buffers // start as 1 kilobytes. initialSize: 1 * 1024 // grow by 1 kilobytes each time buffer overflows. , incrementAmount: 1 * 1024 - }) + })) }) // setup factor bundle, pass in our streamable-buffers as the output source b.plugin(factorBundle, { - o: _.values(outputs) + o: outputs }) // we need to wrap the callback to output an object with all the bundles @@ -234,15 +234,17 @@ ctor = module.exports = function atomifyJs (opts, cb) { if (err && hasCallback) return void cb(err) // turn the stream-able buffers into plain buffers - out = _.mapValues(outputs, function convertStreamToBuffer (stream, entryName) { + out = opts.entries.reduce(function(acc, entryName, ix) { + var stream = outputs[ix] var entryBuffer = stream.getContents() // for those using the streaming interface, emit an event with the entry // do this here so that we don't have to itterate through the outputs twice emitter.emit('entry', entryBuffer, entryName) - return entryBuffer - }) + acc[path.basename(entryName).replace(path.extname(entryName), '')] = entryBuffer + return acc + }, {}) // add in the common bundle out.common = common From 5f77769d2f6e44034df5589f588af8f10eaeb01b Mon Sep 17 00:00:00 2001 From: eggyal Date: Fri, 29 May 2015 10:26:16 +0100 Subject: [PATCH 08/13] Emit abbreviated entry name --- index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 64d9574..6dbc61c 100644 --- a/index.js +++ b/index.js @@ -234,15 +234,16 @@ ctor = module.exports = function atomifyJs (opts, cb) { if (err && hasCallback) return void cb(err) // turn the stream-able buffers into plain buffers - out = opts.entries.reduce(function(acc, entryName, ix) { + out = opts.entries.reduce(function(acc, entry, ix) { var stream = outputs[ix] var entryBuffer = stream.getContents() + var entryName = path.basename(entry).replace(path.extname(entry), '') // for those using the streaming interface, emit an event with the entry // do this here so that we don't have to itterate through the outputs twice emitter.emit('entry', entryBuffer, entryName) - acc[path.basename(entryName).replace(path.extname(entryName), '')] = entryBuffer + acc[entryName] = entryBuffer return acc }, {}) From d1d57ab9083ce5919341821e42d6e18a00efda59 Mon Sep 17 00:00:00 2001 From: eggyal Date: Fri, 29 May 2015 10:47:33 +0100 Subject: [PATCH 09/13] Optionally use user-provided output streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The [documentation for `stream-buffers` states](https://github.com/samcday/node-stream-buffer#disclaimer): > # Disclaimer # > > Not supposed to be a speed demon, it's more for tests/debugging or weird edge cases. It works with an internal buffer that it copies contents to/from/around. Moreover, users may wish to stream the results anyway, so buffering and then converting to a string only then to stream therefrom is rather wasteful. --- index.js | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 6dbc61c..04aabc5 100644 --- a/index.js +++ b/index.js @@ -34,6 +34,7 @@ ctor = module.exports = function atomifyJs (opts, cb) { , assets , outputs , b + , userStreams if (Array.isArray(opts)) opts = {entries: opts} if (typeof opts === 'string') opts = {entries: [opts]} @@ -209,17 +210,28 @@ ctor = module.exports = function atomifyJs (opts, cb) { return void cb(new Error('the `common` option requires an `entries` option with more than one entry')) } - // for each entry, we're going to create a stream-able buffer to put the factored bundle into - outputs = [] - opts.entries.forEach(function createOutputs (entry) { - outputs.push(new streamBuffer.WritableStreamBuffer({ - // these values are arbitrary, but we don't want to require huge buffers - // start as 1 kilobytes. - initialSize: 1 * 1024 - // grow by 1 kilobytes each time buffer overflows. - , incrementAmount: 1 * 1024 - })) - }) + // do some sanity checking on the user-provided streams (if any) + // will fallback to our own buffered streams if these checks fail + userStreams = opts.streams instanceof Array + && opts.streams.length == opts.entries.length + && opts.streams.every(function(s) { + return s && typeof s.pipe === 'function' + }) + + if (userStreams) outputs = opts.streams; + else { + // for each entry, we're going to create a stream-able buffer to put the factored bundle into + outputs = [] + opts.entries.forEach(function createOutputs (entry) { + outputs.push(new streamBuffer.WritableStreamBuffer({ + // these values are arbitrary, but we don't want to require huge buffers + // start as 1 kilobytes. + initialSize: 1 * 1024 + // grow by 1 kilobytes each time buffer overflows. + , incrementAmount: 1 * 1024 + })) + }) + } // setup factor bundle, pass in our streamable-buffers as the output source b.plugin(factorBundle, { From 2cc9eb9ec290478634dfe4063641ae6c5041b3bb Mon Sep 17 00:00:00 2001 From: eggyal Date: Fri, 29 May 2015 23:21:23 +0100 Subject: [PATCH 10/13] Don't convert user output streams to plain buffers --- index.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/index.js b/index.js index 04aabc5..cb9e158 100644 --- a/index.js +++ b/index.js @@ -245,19 +245,21 @@ ctor = module.exports = function atomifyJs (opts, cb) { if (err && hasCallback) return void cb(err) - // turn the stream-able buffers into plain buffers - out = opts.entries.reduce(function(acc, entry, ix) { - var stream = outputs[ix] - var entryBuffer = stream.getContents() - var entryName = path.basename(entry).replace(path.extname(entry), '') - - // for those using the streaming interface, emit an event with the entry - // do this here so that we don't have to itterate through the outputs twice - emitter.emit('entry', entryBuffer, entryName) - - acc[entryName] = entryBuffer - return acc - }, {}) + if (!userStreams) { + // turn the stream-able buffers into plain buffers + out = opts.entries.reduce(function(acc, entry, ix) { + var stream = outputs[ix] + var entryBuffer = stream.getContents() + var entryName = path.basename(entry).replace(path.extname(entry), '') + + // for those using the streaming interface, emit an event with the entry + // do this here so that we don't have to itterate through the outputs twice + emitter.emit('entry', entryBuffer, entryName) + + acc[entryName] = entryBuffer + return acc + }, {}) + } // add in the common bundle out.common = common From e4873eb1cc82321e4d92bfd6200e6f39418f3de0 Mon Sep 17 00:00:00 2001 From: eggyal Date: Sat, 30 May 2015 01:01:23 +0100 Subject: [PATCH 11/13] Documented opts.streams --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3406232..e74daab 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ atomify-js is a tool that makes it easy to create small, atomic modules of clien - [opts.require](#optsrequire) - [opts.external](#optsexternal) - [opts.assets](#optsassets) + - [opts.streams](#optsstreams) - [Callback](#callback) - [Events](#events) - [browserify `( bundle)`](#browserify-browserifyinstance-bundle) @@ -72,7 +73,7 @@ Path or paths that will be provided to Browserify as entry points. For convenien #### opts.common If you have multiple entries, you can set this to `true` to enable [factor-bundle](https://github.com/substack/factor-bundle), which will take the common dependencies of all entries and move them to a common bundle. If you use this option, the api changes a little bit. -If using a callback, you're passed an object that with keys of each entry file and values of the compiled JS file. You'll also have a `common` key. +If a callback is defined, then it will be passed an object whose keys are filenames (stripped of path and file extension) and whose values are the associated compiled JS (as strings). If [opts.streams](#optsstreams) was valid, then this object will only contain a `common` key; else it will also contain one key for every file in [opts.entries](#optsentries). ```js var js = require('atomify-js') @@ -88,7 +89,7 @@ js({ }) ``` -If piping the response, you'll be pipped the common bundle. You'll need to listen to the `'entry'` event to get the compiled entry files. +If piping the response, only the common bundle is piped out. If [opts.streams](#optsstreams) was valid, the other compiled bundles will be piped thereto; otherwise you'll need to listen to the `'entry'` event to get the compiled entry files. ```js var js = require('atomify-js') @@ -172,6 +173,9 @@ and a copy of logo.png will now exist at `dist/assets/4314d804f81c8510.png` You may also provide any valid [browserify bundle options](https://github.com/substack/node-browserify#bbundleopts-cb) in the `opts` object as well, and they will be passed directly to Browserify. +#### opts.streams +An array of streams to which the compiled entry bundles should be piped (in the same order as [opts.entries](#optsentries) is defined). Only meaningful if [opts.common](#opts.common) is `true`. To be valid, this array must be of the same size as [opts.entries](#optsentries) and every element must be a stream; otherwise it will be ignored. + ### Callback Standard Browserify bundle callback with `cb(err, src)` signature. Not called if `opts.output` is specifed. If `callback` is provided as a string rather than function reference it will be used as the `opts.output` file path. From 024f29cb4eb06d13775a43b8f56f9ab605d03c28 Mon Sep 17 00:00:00 2001 From: eggyal Date: Sat, 30 May 2015 09:01:47 +0100 Subject: [PATCH 12/13] Added tests for user-provided output streams --- test/factorBundle.js | 65 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/test/factorBundle.js b/test/factorBundle.js index 56f99f5..be748d3 100644 --- a/test/factorBundle.js +++ b/test/factorBundle.js @@ -136,6 +136,71 @@ test('opts.common: pipes the common bundle', function (t){ }) }) +test('opts.common: streams all bundles', function (t){ + t.plan(9) + + var commonStreamBuffer = new streamBuffer.WritableStreamBuffer() + , entry1StreamBuffer = new streamBuffer.WritableStreamBuffer() + , entry2StreamBuffer = new streamBuffer.WritableStreamBuffer() + + js({ + entries: [ + path.join(prefix, 'entry-1.js') + , path.join(prefix, 'entry-2.js') + ] + , common: true + , streams: [ + entry1StreamBuffer + , entry2StreamBuffer + ] + }) + .on('end', function (){ + var common = commonStreamBuffer.getContents().toString() + , entry1 = entry1StreamBuffer.getContents().toString() + , entry2 = entry2StreamBuffer.getContents().toString() + // the common dep + t.ok( + common.indexOf(dep1) < 0 + , 'common does not contain dep 1' + ) + t.ok( + common.indexOf(dep2) < 0 + , 'common does not contain dep 2' + ) + t.ok( + common.indexOf(depCommon) > -1 + , 'common contains the common dep' + ) + // the first dep + t.ok( + entry1.toString().indexOf(dep1) > -1 + , 'entry-1 contains dep 1' + ) + t.ok( + entry1.toString().indexOf(dep2) < 0 + , 'entry-1 does not contain dep 2' + ) + t.ok( + entry1.toString().indexOf(depCommon) < 0 + , 'entry-1 does not contain the common dep' + ) + // the second dep + t.ok( + entry2.toString().indexOf(dep2) > -1 + , 'entry-2 contains dep 2' + ) + t.ok( + entry2.toString().indexOf(dep1) < 0 + , 'entry-1 does not contain dep 1' + ) + t.ok( + entry2.toString().indexOf(depCommon) < 0 + , 'entry-2 does not contain the common dep' + ) + }) + .pipe(commonStreamBuffer) +}) + test('opts.common: passing the common option without entries', function (t){ t.plan(1) From 3c493bb0f191be764056742269a28616caf3fd86 Mon Sep 17 00:00:00 2001 From: Alexi Margo Date: Sat, 30 May 2015 19:26:42 +0100 Subject: [PATCH 13/13] Watchify user-provided streams --- README.md | 4 +- index.js | 116 +++++++++++++++++++++++-------------------- test/factorBundle.js | 39 ++++++++------- 3 files changed, 83 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index e74daab..ca344da 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ js({ }) ``` -If piping the response, only the common bundle is piped out. If [opts.streams](#optsstreams) was valid, the other compiled bundles will be piped thereto; otherwise you'll need to listen to the `'entry'` event to get the compiled entry files. +If piping the response, only the common bundle is piped out. If [opts.streams](#optsstreams) was valid, the other compiled bundles will be piped to the generated streams; otherwise you'll need to listen to the `'entry'` event to get the compiled entry files. ```js var js = require('atomify-js') @@ -174,7 +174,7 @@ and a copy of logo.png will now exist at `dist/assets/4314d804f81c8510.png` You may also provide any valid [browserify bundle options](https://github.com/substack/node-browserify#bbundleopts-cb) in the `opts` object as well, and they will be passed directly to Browserify. #### opts.streams -An array of streams to which the compiled entry bundles should be piped (in the same order as [opts.entries](#optsentries) is defined). Only meaningful if [opts.common](#opts.common) is `true`. To be valid, this array must be of the same size as [opts.entries](#optsentries) and every element must be a stream; otherwise it will be ignored. +A function that will be called (upon bundling) once per entry file, with two arguments `entry` and `index` (respectively indicating the value and index of the associated element from [opts.entries](#optsentries)); it should return the stream to which the compiled entry bundle should be piped. Only meaningful if [opts.common](#opts.common) is `true`. ### Callback diff --git a/index.js b/index.js index cb9e158..a911037 100644 --- a/index.js +++ b/index.js @@ -34,7 +34,7 @@ ctor = module.exports = function atomifyJs (opts, cb) { , assets , outputs , b - , userStreams + , streamGenerator if (Array.isArray(opts)) opts = {entries: opts} if (typeof opts === 'string') opts = {entries: [opts]} @@ -199,10 +199,6 @@ ctor = module.exports = function atomifyJs (opts, cb) { b.external(opts.external) } - return rebundle() - - function rebundle() { - // if we've got the common option, we want to use factor bundle if (opts.common === true){ if (opts.entries.length < 2) { // TODO: we should do this, but it casues tape to falsely see the error event on itself!? @@ -210,65 +206,75 @@ ctor = module.exports = function atomifyJs (opts, cb) { return void cb(new Error('the `common` option requires an `entries` option with more than one entry')) } - // do some sanity checking on the user-provided streams (if any) - // will fallback to our own buffered streams if these checks fail - userStreams = opts.streams instanceof Array - && opts.streams.length == opts.entries.length - && opts.streams.every(function(s) { - return s && typeof s.pipe === 'function' - }) + // we need a function to generate streams + // users can optionally provide one, else fallback to generating streamable buffers + streamGenerator = _.isFunction(opts.streams) + ? opts.streams + : function() { + return new streamBuffer.WritableStreamBuffer({ + // these values are arbitrary, but we don't want to require huge buffers + // start as 1 kilobytes. + initialSize: 1 * 1024 + // grow by 1 kilobytes each time buffer overflows. + , incrementAmount: 1 * 1024 + }) + } + } - if (userStreams) outputs = opts.streams; - else { - // for each entry, we're going to create a stream-able buffer to put the factored bundle into - outputs = [] - opts.entries.forEach(function createOutputs (entry) { - outputs.push(new streamBuffer.WritableStreamBuffer({ - // these values are arbitrary, but we don't want to require huge buffers - // start as 1 kilobytes. - initialSize: 1 * 1024 - // grow by 1 kilobytes each time buffer overflows. - , incrementAmount: 1 * 1024 - })) - }) - } + return rebundle() - // setup factor bundle, pass in our streamable-buffers as the output source - b.plugin(factorBundle, { - o: outputs - }) + function rebundle() { + // if we've got the common option, we want to use factor bundle + if (opts.common === true){ + // generate the output streams + outputs = opts.entries.reduce(function(acc, entry, ix){ + var s = streamGenerator(entry, ix) + + // sanity check + if (_.isObject(s) && _.isFunction(s.pipe)) { + acc.push(s) + return acc + } else { + return void cb(new Error('if provided, the `streams` option must be a function that returns a stream')) + } + },[]) + + // setup factor bundle + b.plugin(factorBundle, { + // passing in generated streams to receive the output + o: outputs + }) - // we need to wrap the callback to output an object with all the bundles - return b.bundle(function bundledWithCommon (err, common) { - var hasCallback = _.isFunction(cb) - , out = {} + // we need to wrap the callback to output an object with all the bundles + return b.bundle(function bundledWithCommon (err, common) { + var hasCallback = _.isFunction(cb) + , out = {} - if (err && hasCallback) return void cb(err) + if (err && hasCallback) return void cb(err) - if (!userStreams) { - // turn the stream-able buffers into plain buffers - out = opts.entries.reduce(function(acc, entry, ix) { - var stream = outputs[ix] - var entryBuffer = stream.getContents() - var entryName = path.basename(entry).replace(path.extname(entry), '') + if (!_.isFunction(opts.streams)) { + // turn the stream-able buffers into plain buffers + out = opts.entries.reduce(function(acc, entry, ix) { + var entryBuffer = outputs[ix].getContents() + , entryName = path.basename(entry).replace(path.extname(entry), '') - // for those using the streaming interface, emit an event with the entry - // do this here so that we don't have to itterate through the outputs twice - emitter.emit('entry', entryBuffer, entryName) + // for those using the streaming interface, emit an event with the entry + // do this here so that we don't have to itterate through the outputs twice + emitter.emit('entry', entryBuffer, entryName) - acc[entryName] = entryBuffer - return acc - }, {}) - } + acc[entryName] = entryBuffer + return acc + }, {}) + } - // add in the common bundle - out.common = common + // add in the common bundle + out.common = common - if (hasCallback) cb(err, out) - }) - } - // if we don't need to use factor bundle, just browserify! - else return b.bundle(cb) + if (hasCallback) cb(err, out) + }) + } + // if we don't need to use factor bundle, just browserify! + else return b.bundle(cb) } } diff --git a/test/factorBundle.js b/test/factorBundle.js index be748d3..8f13a06 100644 --- a/test/factorBundle.js +++ b/test/factorBundle.js @@ -137,27 +137,28 @@ test('opts.common: pipes the common bundle', function (t){ }) test('opts.common: streams all bundles', function (t){ - t.plan(9) + t.plan(11) var commonStreamBuffer = new streamBuffer.WritableStreamBuffer() - , entry1StreamBuffer = new streamBuffer.WritableStreamBuffer() - , entry2StreamBuffer = new streamBuffer.WritableStreamBuffer() + var buffers = [] + var entries = [ + path.join(prefix, 'entry-1.js') + , path.join(prefix, 'entry-2.js') + ] js({ - entries: [ - path.join(prefix, 'entry-1.js') - , path.join(prefix, 'entry-2.js') - ] + entries: entries , common: true - , streams: [ - entry1StreamBuffer - , entry2StreamBuffer - ] + , streams: function(entry, index) { + t.ok( + entries[index] == entry + , 'buffer generator called with correct arguments' + ) + return buffers[index] = new streamBuffer.WritableStreamBuffer() + } }) .on('end', function (){ var common = commonStreamBuffer.getContents().toString() - , entry1 = entry1StreamBuffer.getContents().toString() - , entry2 = entry2StreamBuffer.getContents().toString() // the common dep t.ok( common.indexOf(dep1) < 0 @@ -173,28 +174,28 @@ test('opts.common: streams all bundles', function (t){ ) // the first dep t.ok( - entry1.toString().indexOf(dep1) > -1 + buffers[0].getContents().toString().indexOf(dep1) > -1 , 'entry-1 contains dep 1' ) t.ok( - entry1.toString().indexOf(dep2) < 0 + buffers[0].getContents().toString().indexOf(dep2) < 0 , 'entry-1 does not contain dep 2' ) t.ok( - entry1.toString().indexOf(depCommon) < 0 + buffers[0].getContents().toString().indexOf(depCommon) < 0 , 'entry-1 does not contain the common dep' ) // the second dep t.ok( - entry2.toString().indexOf(dep2) > -1 + buffers[1].getContents().toString().indexOf(dep2) > -1 , 'entry-2 contains dep 2' ) t.ok( - entry2.toString().indexOf(dep1) < 0 + buffers[1].getContents().toString().indexOf(dep1) < 0 , 'entry-1 does not contain dep 1' ) t.ok( - entry2.toString().indexOf(depCommon) < 0 + buffers[1].getContents().toString().indexOf(depCommon) < 0 , 'entry-2 does not contain the common dep' ) })