Skip to content

Commit

Permalink
feat(stream): Implement dedicated .stream() method for better handl…
Browse files Browse the repository at this point in the history
…ing streams & to pave the way for new stream-related features
  • Loading branch information
shakyShane authored and Shane Osbourne committed Apr 9, 2015
1 parent f5f3d65 commit 2581e7a
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 86 deletions.
12 changes: 11 additions & 1 deletion index.js
Expand Up @@ -58,6 +58,15 @@ module.exports.use = function () {
*/
module.exports.reload = noop("reload");

/**
* The `stream` method returns a transform stream and can act once or on many files.
*
* @method stream
* @param {Object} [opts] Configuration for the stream method
* @returns {*}
*/
module.exports.stream = noop("stream");

/**
* Helper method for browser notifications
*
Expand Down Expand Up @@ -159,7 +168,7 @@ function noop(name) {
if (singleton) {
return singleton[name].apply(singleton, args);
} else {
if (name === "reload" && args[0] && args[0].stream) {
if (name === "stream") {
return utils.noopStream();
}
}
Expand Down Expand Up @@ -248,6 +257,7 @@ function create(name, emitter) {
pause: require("./lib/public/pause")(browserSync),
resume: require("./lib/public/resume")(browserSync),
reload: require("./lib/public/reload")(emitter),
stream: require("./lib/public/stream")(emitter),
cleanup: browserSync.cleanup.bind(browserSync),
use: browserSync.registerPlugin.bind(browserSync),
getOption: browserSync.getOption.bind(browserSync),
Expand Down
70 changes: 15 additions & 55 deletions lib/public/reload.js
@@ -1,8 +1,9 @@
"use strict";

var path = require("path");
var utils = require("../utils");
var _ = require("lodash");
var defaultConfig = require("../default-config");
var stream = require("./stream");

/**
* @param emitter
Expand All @@ -22,12 +23,21 @@ module.exports = function (emitter) {
emitter.emit("browser:reload");
}

function emitInfo(changed) {
emitter.emit("stream:changed", {changed: changed});
}

return function (arg) {

/**
* BACK COMPAT.
* Passing an object as the only arg to the `reload`
* method was only ever used for streams support
* so it's safe to check for that signature here and defer to the
* dedicated `.stream()` method
*/
if (_.isObject(arg)) {
if (!Array.isArray(arg) && Object.keys(arg).length) {
return stream(emitter)(arg);
}
}

if (typeof arg === "string" && arg !== "undefined") {
return emitReload(arg, true);
}
Expand All @@ -43,56 +53,6 @@ module.exports = function (emitter) {
});
}

if (arg && arg.stream === true) {

// Handle Streams here...
var emitted = false;
var once = arg.once || false;
var Transform = require("stream").Transform;
var reload = new Transform({objectMode:true});
var changed = [];

reload._transform = function (file, encoding, next) {

if (once === true && !emitted) {

emitBrowserReload();

emitted = true;

} else { // handle multiple

if (once === true && emitted) {

} else {

if (file.path) {

emitted = true;
emitReload(file.path, false);
changed.push(path.basename(file.path));
}
}
}

this.push(file); // always send the file down-stream

next();
};

reload._flush = function (next) {

if (changed.length) {
emitInfo(changed);
}

next();
};

return reload;
}

return emitBrowserReload();

};
};
74 changes: 74 additions & 0 deletions lib/public/stream.js
@@ -0,0 +1,74 @@
"use strict";

var path = require("path");

/**
* @param emitter
* @returns {Function}
*/
module.exports = function (emitter) {

function emitReload(path, log) {
emitter.emit("file:changed", {
path: path,
log: log,
namespace: "core"
});
}

function emitBrowserReload() {
emitter.emit("browser:reload");
}

function emitInfo(changed) {
emitter.emit("stream:changed", {changed: changed});
}

return function (opts) {

opts = opts || {};
var emitted = false;
var Transform = require("stream").Transform;
var reload = new Transform({objectMode: true});
var changed = [];

reload._transform = function (file, encoding, next) {

if (opts.once === true && !emitted) {

emitBrowserReload();

emitted = true;

} else { // handle multiple

if (opts.once === true && emitted) {

} else {

if (file.path) {

emitted = true;
emitReload(file.path, false);
changed.push(path.basename(file.path));
}
}
}

this.push(file); // always send the file down-stream

next();
};

reload._flush = function (next) {

if (changed.length) {
emitInfo(changed);
}

next();
};

return reload;
};
};
10 changes: 10 additions & 0 deletions test/specs/api/init.reload.js
Expand Up @@ -4,6 +4,7 @@ var browserSync = require("../../../");

var sinon = require("sinon");
var assert = require("chai").assert;
var File = require("vinyl");

describe("API: .reload()", function () {

Expand Down Expand Up @@ -66,4 +67,13 @@ describe("API: .reload()", function () {
browserSync.reload(["index.html", "css/core.css"]);
sinon.assert.calledWithExactly(emitterStub, "browser:reload");
});
it("should reload browser if once:true given as arg", function () {
var stream = browserSync.reload({stream: true, once: true});
stream.write(new File({path: "styles.css"}));
stream.write(new File({path: "styles2.css"}));
stream.write(new File({path: "styles3.css"}));
stream.end();
sinon.assert.calledOnce(emitterStub);
sinon.assert.calledWithExactly(emitterStub, "browser:reload");
});
});
30 changes: 5 additions & 25 deletions test/specs/api/init.reload.stream.js
Expand Up @@ -5,7 +5,7 @@ var browserSync = require("../../../");
var sinon = require("sinon");
var File = require("vinyl");

describe("API: .reload()", function () {
describe("API: .stream()", function () {

var emitterStub, clock, bs;

Expand All @@ -30,9 +30,7 @@ describe("API: .reload()", function () {
});

it("should handle a single file changed", function () {
var stream = browserSync.reload({
stream: true
});
var stream = browserSync.stream();
stream.write(new File({path: "styles.css"}));
stream.end();
sinon.assert.calledWithExactly(emitterStub, "file:changed", {
Expand All @@ -42,7 +40,7 @@ describe("API: .reload()", function () {
});
});
it("should accept multiple files in stream", function () {
var stream = browserSync.reload({stream: true});
var stream = browserSync.stream();
stream.write(new File({path: "styles.css"}));
stream.write(new File({path: "styles2.css"}));
stream.end();
Expand All @@ -61,34 +59,16 @@ describe("API: .reload()", function () {
});
});
it("should reload browser if once:true given as arg", function () {
var stream = browserSync.reload({stream: true, once: true});
var stream = browserSync.stream({once: true});
stream.write(new File({path: "styles.css"}));
stream.write(new File({path: "styles2.css"}));
stream.write(new File({path: "styles3.css"}));
stream.end();
sinon.assert.calledOnce(emitterStub);
sinon.assert.calledWithExactly(emitterStub, "browser:reload");
});
it("should be able to call .reload after a stream", function () {
browserSync.reload();
sinon.assert.calledWithExactly(emitterStub, "browser:reload");

var stream = browserSync.reload({stream: true});
stream.write(new File({path: "styles.css"}));
stream.end();

sinon.assert.calledWithExactly(emitterStub, "browser:reload");
sinon.assert.calledWithExactly(emitterStub, "file:changed", {
path: "styles.css",
log: false,
namespace: "core"
});
sinon.assert.calledWithExactly(emitterStub, "stream:changed", {
changed: ["styles.css"]
});
});
it("does not log file info if (once: true)", function () {
var stream = browserSync.reload({stream: true, once: true});
var stream = browserSync.stream({once: true});
stream.write(new File({path: "styles.js"}));
stream.write(new File({path: "styles2.js"}));
stream.write(new File({path: "styles3.js"}));
Expand Down
8 changes: 3 additions & 5 deletions test/specs/api/init.reload.stream.noop.js
Expand Up @@ -5,17 +5,15 @@ var assert = require("chai").assert;
var File = require("vinyl");
var sinon = require("sinon");

describe("API: .reload()", function () {
describe("API: .stream() noop", function () {

before(function () {
browserSync.reset();
});

it("should can handle a reload + stream call when there's no instance", function () {
assert.doesNotThrow(function () {
var stream = browserSync.reload({
stream: true
});
var stream = browserSync.stream();
stream.write(new File({path: "styles.css"}));
stream.end();
});
Expand All @@ -24,7 +22,7 @@ describe("API: .reload()", function () {
var emitterStub;
var bs = browserSync(function () {

var stream = bs.reload({stream:true});
var stream = bs.stream();

emitterStub = sinon.spy(bs.emitter, "emit");

Expand Down

0 comments on commit 2581e7a

Please sign in to comment.