Skip to content

Commit

Permalink
feat(commands): Add reload command for http-protocol comms
Browse files Browse the repository at this point in the history
  • Loading branch information
shakyShane committed Apr 8, 2015
1 parent db8673a commit c0fe70d
Show file tree
Hide file tree
Showing 15 changed files with 132 additions and 82 deletions.
62 changes: 33 additions & 29 deletions bin/browser-sync.js
Expand Up @@ -6,9 +6,7 @@ var fs = require("fs");
var path = require("path");
var compile = require("eazy-logger").compile;
var utils = require("../lib/utils");
var flags = require("../lib/cli/opts");
var flagKeys = Object.keys(flags);

var logger = require("../lib/logger").logger;
var cmdWhitelist = ["start", "init", "reload"];

var cli = meow({
Expand All @@ -29,20 +27,23 @@ if (!module.parent) {
* @returns {String}
*/
function getHelpText(filepath) {
return compile(
fs.readFileSync(
filepath,
"utf8"
).replace(
"%flags%",
listFlags(
flags,
longest(
flagKeys
).length
)
)
);

/**
* Help text template
*/
var template = fs.readFileSync(filepath, "utf8");

cmdWhitelist.forEach(function (command) {

var flags = require("../lib/cli/opts." + command + ".json");

template = template.replace(
["%", command, "flags%"].join(""),
listFlags(flags)
);
});

return compile(template);
}

/**
Expand All @@ -54,7 +55,6 @@ function handleCli (opts) {
opts.cb = opts.cb || utils.defaultCallback;

var input = opts.cli.input;
var flags = opts.cli.flags;

if (!opts.whitelist) {
opts.whitelist = cmdWhitelist;
Expand All @@ -64,24 +64,28 @@ function handleCli (opts) {
return console.log(opts.cli.help);
}

if (input[0] === "start") {
require("../lib/cli/command.start")(opts);
}

if (input[0] === "init") {
require("../lib/cli/command.init")(opts);
if (!require("../lib/cli/cli-utils").verifyOpts(input[0], opts.cli.flags)) {
logger.info("For help, run: {cyan:browser-sync --help}");
return opts.cb(new Error("Unknown flag given. Please refer to the documentation for help."));
}

return require("../lib/cli/command." + input[0])(opts);
}

/**
* @param {Object} flags
* @param {Number} longest
* @returns {String}
*/
function listFlags (flags, longest) {
function listFlags (flags) {

var flagKeys = Object.keys(flags);
var longest = getLongest(Object.keys(flags));

if (!longest || !longest.length) {
return;
}

return flagKeys.reduce(function (all, item) {
return all + " {bold:--" + item + "}" + getPadding(item.length, longest + 8) + flags[item] + "\n";
return all + " {bold:--" + item + "}" + getPadding(item.length, longest.length + 8) + flags[item] + "\n";
}, "");
}

Expand All @@ -98,7 +102,7 @@ function getPadding (len, max) {
* @param {Array} arr
* @returns {String}
*/
function longest (arr) {
function getLongest (arr) {
return arr.sort(function (a, b) { return b.length - a.length; })[0];
}

Expand Down
6 changes: 1 addition & 5 deletions lib/async.js
Expand Up @@ -234,16 +234,12 @@ module.exports = {
*/
addHttpProtocol: function (bs, done) {

if (!bs.options.get("httpProtocol")) {
return done(null);
}

/**
* Add a middleware to listen to http
* requests in the BrowserSync http protocol namespace
*/
bs.addMiddleware(
bs.options.getIn(["httpProtocol", "path"]),
require("./config").httpProtocol.path,
require("./http-protocol").middleware(bs),
{override: true}
);
Expand Down
16 changes: 13 additions & 3 deletions lib/cli/cli-utils.js
Expand Up @@ -2,11 +2,13 @@

var utils = exports;
var logger = require("../logger").logger;
var flags = require("./opts.json");
var flagKeys = Object.keys(flags);
var _ = require("lodash");

utils.verifyOpts = function (flagWhitelist, cliFlags) {
utils.verifyOpts = function (optskey, cliFlags) {

var flags = require("./opts." + optskey + ".json");
var flagKeys = Object.keys(flags);
var flagWhitelist = flagKeys.map(dropPrefix).map(_.camelCase);

return Object.keys(cliFlags).every(function (key) {

Expand All @@ -19,3 +21,11 @@ utils.verifyOpts = function (flagWhitelist, cliFlags) {
return false;
});
};

/**
* @param {String} item
* @returns {String}
*/
function dropPrefix (item) {
return item.replace("no-", "");
}
29 changes: 29 additions & 0 deletions lib/cli/command.reload.js
@@ -0,0 +1,29 @@
"use strict";

var error = "Could not contact BrowserSync server.";

/**
* $ browser-sync reload <options>
*
* This commands starts the BrowserSync servers
* & Optionally UI.
*
* @param opts
* @returns {Function}
*/
module.exports = function (opts) {

var flags = opts.cli.flags;
var proto = require("../http-protocol");

var url = proto.getUrl({method: "reload", args: flags.files}, "http://localhost:" + (flags.port || 3000));

require("http").get(url, function (res) {
if (res.statusCode !== 200) {
require("logger").logger.error(error);
return opts.cb(new Error(error));
} else {
opts.cb(null, res);
}
});
};
20 changes: 1 addition & 19 deletions lib/cli/command.start.js
@@ -1,11 +1,6 @@
"use strict";

var logger = require("../logger").logger;
var info = require("./cli-info");
var flags = require("./opts.json");
var _ = require("lodash");
var flagKeys = Object.keys(flags);
var flagWhitelist = flagKeys.map(dropPrefix).map(_.camelCase);
var info = require("./cli-info");

/**
* $ browser-sync start <options>
Expand All @@ -20,20 +15,7 @@ module.exports = function (opts) {

var flags = opts.cli.flags;

if (!require("./cli-utils").verifyOpts(flagWhitelist, flags)) {
logger.info("For help, run: {cyan:browser-sync --help}");
return opts.cb(new Error("Unknown flag given. Please refer to the documentation for help."));
}

return require("../../")
.create("cli")
.init(flags.config ? info.getConfigFile(flags.config) : flags, opts.cb);
};

/**
* @param {String} item
* @returns {String}
*/
function dropPrefix (item) {
return item.replace("no-", "");
}
10 changes: 8 additions & 2 deletions lib/cli/help.txt
Expand Up @@ -8,11 +8,17 @@

{bold:init} Creates a default config file
{bold:start} Start Browser Sync
{bold:reload} Send a reload event over HTTP protocol

{bold:Options:}
{bold:`start` Options:}
{gray:--------}

%flags%
%startflags%

{bold:`reload` Options:}
{gray:--------}

%reloadflags%

{cyan:Server Example:}
{gray:---------------}
Expand Down
1 change: 1 addition & 0 deletions lib/cli/opts.init.json
@@ -0,0 +1 @@
{}
4 changes: 4 additions & 0 deletions lib/cli/opts.reload.json
@@ -0,0 +1,4 @@
{
"files": "File paths to reload",
"port": "Target a running instance by port number"
}
File renamed without changes.
3 changes: 3 additions & 0 deletions lib/config.js
Expand Up @@ -17,6 +17,9 @@ module.exports = {
configFile: "/default-config.js",
userFile: "/bs-config.js",
template: "/cli-template.js",
httpProtocol: {
path: "/__browser_sync__"
},
client: {
shims: "/client/client-shims.js"
},
Expand Down
10 changes: 0 additions & 10 deletions lib/default-config.js
Expand Up @@ -339,16 +339,6 @@ module.exports = {
}
},

/**
* @property httpProtocol
* @param {String} [path="/__browser_sync__"]
* @since 2.6.0
* @type Object
*/
httpProtocol: {
path: "/__browser_sync__"
},

/**
* A map of file-extensions -> dom element.
* Useful if you're serving files with unusual file extensions
Expand Down
8 changes: 4 additions & 4 deletions lib/http-protocol.js
Expand Up @@ -12,13 +12,13 @@ var proto = exports;
* Eg. http://localhost:3000/__browser_sync__?method=reload&args=core.css&args=core.min
*
* @param args
* @param bs
* @param url
* @returns {string}
*/
proto.getUrl = function (args, bs) {
proto.getUrl = function (args, url) {
return [
bs.options.getIn(["urls", "local"]),
bs.options.getIn(["httpProtocol", "path"]),
url,
require("./config").httpProtocol.path,
"?",
queryString.stringify(args)
].join("");
Expand Down
2 changes: 1 addition & 1 deletion lib/public/reload.js
Expand Up @@ -28,7 +28,7 @@ module.exports = function (emitter) {

return function (arg) {

if (typeof arg === "string") {
if (typeof arg === "string" && arg !== "undefined") {
return emitReload(arg, true);
}

Expand Down
37 changes: 31 additions & 6 deletions test/specs/commands/reload.js
@@ -1,19 +1,16 @@
"use strict";

var path = require("path");
//var utils = require("../../../lib/utils");
//var assert = require("chai").assert;
var browserSync = require(path.resolve("./"));

var pkg = require(path.resolve("package.json"));
var sinon = require("sinon");
var cli = require(path.resolve(pkg.bin));

describe.skip("E2E CLI `reload` with no files arg", function () {
it("should make a http request to the protocol", function (done) {
describe("E2E CLI `reload` with no files arg", function () {

it("should make a http request to the protocol with no files arg", function (done) {
browserSync.reset();

browserSync
.create()
.init({server: "test/fixtures", open: false}, function (err, bs) {
Expand All @@ -28,7 +25,35 @@ describe.skip("E2E CLI `reload` with no files arg", function () {
}
},
cb: function () {
sinon.assert.called(spy);
sinon.assert.calledWithExactly(spy, "browser:reload");
bs.cleanup();
done();
}
});
});
});

it("should make a http request with files arg", function (done) {

browserSync.reset();

browserSync
.create()
.init({server: "test/fixtures", open: false}, function (err, bs) {

var spy = sinon.spy(bs.events, "emit");

cli({
cli: {
input: ["reload"],
flags: {
port: bs.options.get("port"),
files: "core.css"
}
},
cb: function () {
sinon.assert.calledWithExactly(spy, "file:changed", {path: "core.css", log: true, namespace: "core"});
bs.cleanup();
done();
}
});
Expand Down
6 changes: 3 additions & 3 deletions test/specs/http-protocol/http.reload.js
Expand Up @@ -36,7 +36,7 @@ describe("HTTP protocol", function () {

it("responds to reload event with no args", function (done) {

var url = proto.getUrl({method: "reload"}, bs);
var url = proto.getUrl({method: "reload"}, bs.options.getIn(["urls", "local"]));

request(url, function (e, r, body) {
sinon.assert.calledWith(spy, "browser:reload");
Expand All @@ -47,7 +47,7 @@ describe("HTTP protocol", function () {
});
it("responds to reload event with multi file paths", function (done) {

var url = proto.getUrl({method: "reload", args: ["core.min.css", "core.css"]}, bs);
var url = proto.getUrl({method: "reload", args: ["core.min.css", "core.css"]}, bs.options.getIn(["urls", "local"]));

request(url, function (e, r, body) {
sinon.assert.calledWith(spy, "file:changed");
Expand All @@ -59,7 +59,7 @@ describe("HTTP protocol", function () {
});
it("responds to reload event with single file path", function (done) {

var url = proto.getUrl({method: "reload", args: "somefile.php"}, bs);
var url = proto.getUrl({method: "reload", args: "somefile.php"}, bs.options.getIn(["urls", "local"]));

request(url, function (e, r, body) {
sinon.assert.calledWith(spy, "file:changed");
Expand Down

0 comments on commit c0fe70d

Please sign in to comment.