connect-utils.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. "use strict";
  2. var _ = require("./lodash.custom");
  3. var fs = require("fs");
  4. var config = require("./config");
  5. function getPath(options, relative, port) {
  6. if (options.get("mode") === "snippet") {
  7. return options.get("scheme") + "://HOST:" + port + relative;
  8. }
  9. else {
  10. return "//HOST:" + port + relative;
  11. }
  12. }
  13. var connectUtils = {
  14. /**
  15. * @param {Immutable.Map} options
  16. * @returns {String}
  17. */
  18. scriptTags: function (options) {
  19. var scriptPath = this.clientScript(options);
  20. var async = options.getIn(["snippetOptions", "async"]);
  21. var scriptDomain = options.getIn(["script", "domain"]);
  22. /**
  23. * Generate the [src] attribute based on user options
  24. */
  25. var scriptSrc = (function () {
  26. if (options.get("localOnly")) {
  27. return [
  28. options.get("scheme"),
  29. "://localhost:",
  30. options.get("port"),
  31. scriptPath
  32. ].join("");
  33. }
  34. /**
  35. * First, was "scriptPath" set? if so the user wanted full control over the
  36. * script tag output
  37. *
  38. */
  39. if (_.isFunction(options.get("scriptPath"))) {
  40. return options
  41. .get("scriptPath")
  42. .apply(null, getScriptArgs(options, scriptPath));
  43. }
  44. /**
  45. * Next, if "script.domain" was given, allow that + the path to the JS file
  46. * eg:
  47. * script.domain=localhost:3000
  48. * -> localhost:3000/browser-sync/browser-sync-client.js
  49. */
  50. if (scriptDomain) {
  51. if (_.isFunction(scriptDomain)) {
  52. return scriptDomain.call(null, options) + scriptPath;
  53. }
  54. if (scriptDomain.match(/\{port\}/)) {
  55. return (scriptDomain.replace("{port}", options.get("port")) +
  56. scriptPath);
  57. }
  58. return scriptDomain + scriptPath;
  59. }
  60. /**
  61. * Now if server or proxy, use dynamic script
  62. * eg:
  63. * browser-sync start --server
  64. * ->
  65. * "HOST:3000/browser-sync/browser-sync-client.js".replace("HOST", location.hostname)
  66. */
  67. if (options.get("server") || options.get("proxy")) {
  68. return scriptPath;
  69. }
  70. /**
  71. * Final use case is snippet mode
  72. * -> "http://HOST:3000/browser-sync/browser-sync-client.js".replace("HOST", location.hostname)
  73. * -> "//HOST:3000/browser-sync/browser-sync-client.js".replace("HOST", location.hostname)"
  74. */
  75. return getPath(options, scriptPath, options.get("port"));
  76. })();
  77. /**
  78. * Decide which template shall be used to generate the script tags
  79. */
  80. var template = (function () {
  81. if (scriptDomain || options.get("localOnly")) {
  82. return config.templates.scriptTagSimple;
  83. }
  84. return config.templates.scriptTag;
  85. })();
  86. /**
  87. * Finally read the template file from disk and replace
  88. * the dynamic values.
  89. */
  90. return fs
  91. .readFileSync(template, "utf8")
  92. .replace("%script%", scriptSrc)
  93. .replace("%async%", async ? "async" : "");
  94. },
  95. /**
  96. * @param {Map} options
  97. * @returns {String}
  98. */
  99. socketConnector: function (options) {
  100. var socket = options.get("socket");
  101. var template = fs.readFileSync(config.templates.connector, "utf-8");
  102. var url = connectUtils.getConnectionUrl(options);
  103. /**
  104. * ***Backwards compatibility***. While `socket.path` is technically a
  105. * socketIoClientConfig property, it's been documented previously
  106. * as a top-level option, so must stay.
  107. */
  108. var clientConfig = socket.get("socketIoClientConfig").merge({
  109. path: socket.get("path")
  110. });
  111. template = template
  112. .replace("%config%", JSON.stringify(clientConfig.toJS()))
  113. .replace("%options%", JSON.stringify(options))
  114. .replace("%url%", url);
  115. return template;
  116. },
  117. /**
  118. * @param {Object} socketOpts
  119. * @param {Map} options
  120. * @returns {String|Function}
  121. */
  122. getNamespace: function (socketOpts, options) {
  123. var namespace = socketOpts.namespace;
  124. if (typeof namespace === "function") {
  125. return namespace(options);
  126. }
  127. if (!namespace.match(/^\//)) {
  128. namespace = "/" + namespace;
  129. }
  130. return namespace;
  131. },
  132. /**
  133. * @param {Map} options
  134. * @returns {string}
  135. */
  136. getConnectionUrl: function (options) {
  137. var socketOpts = options.get("socket").toJS();
  138. var namespace = connectUtils.getNamespace(socketOpts, options);
  139. var protocol = "";
  140. var withHostnamePort = "'{protocol}' + location.hostname + ':{port}{ns}'";
  141. var withHost = "'{protocol}' + location.host + '{ns}'";
  142. var withDomain = "'{domain}{ns}'";
  143. var port = options.get("port");
  144. // default use-case is server/proxy
  145. var string = withHost;
  146. if (options.get("mode") !== "server") {
  147. protocol = options.get("scheme") + "://";
  148. string = withHostnamePort;
  149. }
  150. if (options.get("mode") === "proxy" && options.getIn(["proxy", "ws"])) {
  151. port = options.getIn(["socket", "port"]);
  152. }
  153. /**
  154. * Ensure socket.domain is always a string (for noop replacements later)
  155. */
  156. socketOpts.domain = (function () {
  157. if (options.get("localOnly")) {
  158. string = withDomain;
  159. return [
  160. options.get("scheme"),
  161. "://localhost:",
  162. options.get("port")
  163. ].join("");
  164. }
  165. if (socketOpts.domain) {
  166. string = withDomain;
  167. /**
  168. * User provided a function
  169. */
  170. if (_.isFunction(socketOpts.domain)) {
  171. return socketOpts.domain.call(null, options);
  172. }
  173. /**
  174. * User provided a string
  175. */
  176. if (_.isString(socketOpts.domain)) {
  177. return socketOpts.domain;
  178. }
  179. }
  180. return "";
  181. })();
  182. return string
  183. .replace("{protocol}", protocol)
  184. .replace("{port}", port)
  185. .replace("{domain}", socketOpts.domain.replace("{port}", port))
  186. .replace("{ns}", namespace);
  187. },
  188. /**
  189. * @param {Object} [options]
  190. * @param {Boolean} [both]
  191. */
  192. clientScript: function (options, both) {
  193. var prefix = options.getIn(["socket", "clientPath"]);
  194. var script = prefix + "/browser-sync-client.js";
  195. var versioned = prefix + "/browser-sync-client.js?v=" + options.get("version");
  196. if (both) {
  197. return {
  198. path: script,
  199. versioned: versioned
  200. };
  201. }
  202. return versioned;
  203. }
  204. };
  205. /**
  206. * @param options
  207. * @returns {*[]}
  208. */
  209. function getScriptArgs(options, scriptPath) {
  210. var abspath = options.get("scheme") + "://HOST:" + options.get("port") + scriptPath;
  211. return [scriptPath, options.get("port"), options.set("absolute", abspath)];
  212. }
  213. module.exports = connectUtils;
  214. //# sourceMappingURL=connect-utils.js.map