246 lines
7.5 KiB
JavaScript
246 lines
7.5 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
var _ = require("../lodash.custom");
|
||
|
var fs = require("fs");
|
||
|
var config = require("./config");
|
||
|
|
||
|
function getPath(options, relative, port) {
|
||
|
if (options.get("mode") === "snippet") {
|
||
|
return options.get("scheme") + "://HOST:" + port + relative;
|
||
|
} else {
|
||
|
return "//HOST:" + port + relative;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var connectUtils = {
|
||
|
/**
|
||
|
* @param {Immutable.Map} options
|
||
|
* @returns {String}
|
||
|
*/
|
||
|
scriptTags: function (options) {
|
||
|
|
||
|
var scriptPath = this.clientScript(options);
|
||
|
var async = options.getIn(["snippetOptions", "async"]);
|
||
|
var scriptDomain = options.getIn(["script", "domain"]);
|
||
|
|
||
|
/**
|
||
|
* Generate the [src] attribute based on user options
|
||
|
*/
|
||
|
var scriptSrc = (function () {
|
||
|
|
||
|
if (options.get("localOnly")) {
|
||
|
return [
|
||
|
options.get("scheme"),
|
||
|
"://localhost:",
|
||
|
options.get("port"),
|
||
|
scriptPath
|
||
|
].join("");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* First, was "scriptPath" set? if so the user wanted full control over the
|
||
|
* script tag output
|
||
|
*
|
||
|
*/
|
||
|
if (_.isFunction(options.get("scriptPath"))) {
|
||
|
return options.get("scriptPath").apply(null, getScriptArgs(options, scriptPath));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Next, if "script.domain" was given, allow that + the path to the JS file
|
||
|
* eg:
|
||
|
* script.domain=localhost:3000
|
||
|
* -> localhost:3000/browser-sync/browser-sync-client.js
|
||
|
*/
|
||
|
if (scriptDomain) {
|
||
|
if (_.isFunction(scriptDomain)) {
|
||
|
return scriptDomain.call(null, options) + scriptPath;
|
||
|
}
|
||
|
if (scriptDomain.match(/\{port\}/)) {
|
||
|
return scriptDomain.replace("{port}", options.get("port")) + scriptPath;
|
||
|
}
|
||
|
return scriptDomain + scriptPath;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Now if server or proxy, use dynamic script
|
||
|
* eg:
|
||
|
* browser-sync start --server
|
||
|
* ->
|
||
|
* "HOST:3000/browser-sync/browser-sync-client.js".replace("HOST", location.hostname)
|
||
|
*/
|
||
|
if (options.get("server") || options.get("proxy")) {
|
||
|
return scriptPath;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Final use case is snippet mode
|
||
|
* -> "http://HOST:3000/browser-sync/browser-sync-client.js".replace("HOST", location.hostname)
|
||
|
* -> "//HOST:3000/browser-sync/browser-sync-client.js".replace("HOST", location.hostname)"
|
||
|
*/
|
||
|
return getPath(options, scriptPath, options.get("port"));
|
||
|
})();
|
||
|
|
||
|
/**
|
||
|
* Decide which template shall be used to generate the script tags
|
||
|
*/
|
||
|
var template = (function () {
|
||
|
if (scriptDomain || options.get("localOnly")) {
|
||
|
return config.templates.scriptTagSimple;
|
||
|
}
|
||
|
return config.templates.scriptTag;
|
||
|
})();
|
||
|
|
||
|
/**
|
||
|
* Finally read the template file from disk and replace
|
||
|
* the dynamic values.
|
||
|
*/
|
||
|
return fs.readFileSync(template, "utf8")
|
||
|
.replace("%script%", scriptSrc)
|
||
|
.replace("%async%", async ? "async" : "");
|
||
|
},
|
||
|
/**
|
||
|
* @param {Map} options
|
||
|
* @returns {String}
|
||
|
*/
|
||
|
socketConnector: function (options) {
|
||
|
|
||
|
var socket = options.get("socket");
|
||
|
var template = fs.readFileSync(config.templates.connector, "utf-8");
|
||
|
var url = connectUtils.getConnectionUrl(options);
|
||
|
|
||
|
/**
|
||
|
* ***Backwards compatibility***. While `socket.path` is technically a
|
||
|
* socketIoClientConfig property, it's been documented previously
|
||
|
* as a top-level option, so must stay.
|
||
|
*/
|
||
|
var clientConfig = socket
|
||
|
.get("socketIoClientConfig")
|
||
|
.merge({
|
||
|
path: socket.get("path")
|
||
|
});
|
||
|
|
||
|
template = template
|
||
|
.replace("%config%", JSON.stringify(clientConfig.toJS()))
|
||
|
.replace("%url%", url);
|
||
|
|
||
|
return template;
|
||
|
},
|
||
|
/**
|
||
|
* @param {Object} socketOpts
|
||
|
* @param {Map} options
|
||
|
* @returns {String|Function}
|
||
|
*/
|
||
|
getNamespace: function (socketOpts, options) {
|
||
|
|
||
|
var namespace = socketOpts.namespace;
|
||
|
|
||
|
if (typeof namespace === "function") {
|
||
|
return namespace(options);
|
||
|
}
|
||
|
|
||
|
if (!namespace.match(/^\//)) {
|
||
|
namespace = "/" + namespace;
|
||
|
}
|
||
|
|
||
|
return namespace;
|
||
|
},
|
||
|
/**
|
||
|
* @param {Map} options
|
||
|
* @returns {string}
|
||
|
*/
|
||
|
getConnectionUrl: function (options) {
|
||
|
|
||
|
var socketOpts = options.get("socket").toJS();
|
||
|
var namespace = connectUtils.getNamespace(socketOpts, options);
|
||
|
|
||
|
var protocol = "";
|
||
|
var withHostnamePort = "'{protocol}' + location.hostname + ':{port}{ns}'";
|
||
|
var withHost = "'{protocol}' + location.host + '{ns}'";
|
||
|
var withDomain = "'{domain}{ns}'";
|
||
|
var port = options.get("port");
|
||
|
|
||
|
// default use-case is server/proxy
|
||
|
var string = withHost;
|
||
|
|
||
|
if (options.get("mode") !== "server") {
|
||
|
protocol = options.get("scheme") + "://";
|
||
|
string = withHostnamePort;
|
||
|
}
|
||
|
|
||
|
if (options.get("mode") === "proxy" && options.getIn(["proxy", "ws"])) {
|
||
|
port = options.getIn(["socket", "port"]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Ensure socket.domain is always a string (for noop replacements later)
|
||
|
*/
|
||
|
socketOpts.domain = (function () {
|
||
|
if (options.get("localOnly")) {
|
||
|
string = withDomain;
|
||
|
return [
|
||
|
options.get("scheme"),
|
||
|
"://localhost:",
|
||
|
options.get("port")
|
||
|
].join("");
|
||
|
}
|
||
|
if (socketOpts.domain) {
|
||
|
string = withDomain;
|
||
|
/**
|
||
|
* User provided a function
|
||
|
*/
|
||
|
if (_.isFunction(socketOpts.domain)) {
|
||
|
return socketOpts.domain.call(null, options);
|
||
|
}
|
||
|
/**
|
||
|
* User provided a string
|
||
|
*/
|
||
|
if (_.isString(socketOpts.domain)) {
|
||
|
return socketOpts.domain;
|
||
|
}
|
||
|
}
|
||
|
return "";
|
||
|
})();
|
||
|
|
||
|
return string
|
||
|
.replace("{protocol}", protocol)
|
||
|
.replace("{port}", port)
|
||
|
.replace("{domain}", socketOpts.domain.replace("{port}", port))
|
||
|
.replace("{ns}", namespace);
|
||
|
},
|
||
|
/**
|
||
|
* @param {Object} [options]
|
||
|
* @param {Boolean} [both]
|
||
|
*/
|
||
|
clientScript: function (options, both) {
|
||
|
|
||
|
var prefix = options.getIn(["socket", "clientPath"]);
|
||
|
var script = prefix + "/browser-sync-client.js";
|
||
|
var versioned = prefix + "/browser-sync-client.js?v=" + options.get("version");
|
||
|
|
||
|
if (both) {
|
||
|
return {
|
||
|
path: script,
|
||
|
versioned: versioned
|
||
|
};
|
||
|
}
|
||
|
|
||
|
return versioned;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @param options
|
||
|
* @returns {*[]}
|
||
|
*/
|
||
|
function getScriptArgs (options, scriptPath) {
|
||
|
var abspath = options.get("scheme") + "://HOST:" + options.get("port") + scriptPath;
|
||
|
return [
|
||
|
scriptPath,
|
||
|
options.get("port"),
|
||
|
options.set("absolute", abspath)
|
||
|
];
|
||
|
}
|
||
|
|
||
|
module.exports = connectUtils;
|