namespace.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.Namespace = void 0;
  7. const socket_1 = require("./socket");
  8. const events_1 = require("events");
  9. const socket_io_parser_1 = require("socket.io-parser");
  10. const debug_1 = __importDefault(require("debug"));
  11. const debug = debug_1.default("socket.io:namespace");
  12. class Namespace extends events_1.EventEmitter {
  13. /**
  14. * Namespace constructor.
  15. *
  16. * @param {Server} server instance
  17. * @param {string} name
  18. */
  19. constructor(server, name) {
  20. super();
  21. this.sockets = new Map();
  22. /** @private */
  23. this._fns = [];
  24. /** @private */
  25. this._rooms = new Set();
  26. /** @private */
  27. this._flags = {};
  28. /** @private */
  29. this._ids = 0;
  30. this.server = server;
  31. this.name = name;
  32. this._initAdapter();
  33. }
  34. /**
  35. * Initializes the `Adapter` for this nsp.
  36. * Run upon changing adapter by `Server#adapter`
  37. * in addition to the constructor.
  38. *
  39. * @private
  40. */
  41. _initAdapter() {
  42. this.adapter = new (this.server.adapter())(this);
  43. }
  44. /**
  45. * Sets up namespace middleware.
  46. *
  47. * @return {Namespace} self
  48. * @public
  49. */
  50. use(fn) {
  51. this._fns.push(fn);
  52. return this;
  53. }
  54. /**
  55. * Executes the middleware for an incoming client.
  56. *
  57. * @param {Socket} socket - the socket that will get added
  58. * @param {Function} fn - last fn call in the middleware
  59. * @private
  60. */
  61. run(socket, fn) {
  62. const fns = this._fns.slice(0);
  63. if (!fns.length)
  64. return fn(null);
  65. function run(i) {
  66. fns[i](socket, function (err) {
  67. // upon error, short-circuit
  68. if (err)
  69. return fn(err);
  70. // if no middleware left, summon callback
  71. if (!fns[i + 1])
  72. return fn(null);
  73. // go on to next
  74. run(i + 1);
  75. });
  76. }
  77. run(0);
  78. }
  79. /**
  80. * Targets a room when emitting.
  81. *
  82. * @param {String} name
  83. * @return {Namespace} self
  84. * @public
  85. */
  86. to(name) {
  87. this._rooms.add(name);
  88. return this;
  89. }
  90. /**
  91. * Targets a room when emitting.
  92. *
  93. * @param {String} name
  94. * @return {Namespace} self
  95. * @public
  96. */
  97. in(name) {
  98. this._rooms.add(name);
  99. return this;
  100. }
  101. /**
  102. * Adds a new client.
  103. *
  104. * @return {Socket}
  105. * @private
  106. */
  107. _add(client, query, fn) {
  108. debug("adding socket to nsp %s", this.name);
  109. const socket = new socket_1.Socket(this, client, query);
  110. this.run(socket, err => {
  111. process.nextTick(() => {
  112. if ("open" == client.conn.readyState) {
  113. if (err)
  114. return socket._error({
  115. message: err.message,
  116. data: err.data
  117. });
  118. // track socket
  119. this.sockets.set(socket.id, socket);
  120. // it's paramount that the internal `onconnect` logic
  121. // fires before user-set events to prevent state order
  122. // violations (such as a disconnection before the connection
  123. // logic is complete)
  124. socket._onconnect();
  125. if (fn)
  126. fn();
  127. // fire user-set events
  128. super.emit("connect", socket);
  129. super.emit("connection", socket);
  130. }
  131. else {
  132. debug("next called after client was closed - ignoring socket");
  133. }
  134. });
  135. });
  136. return socket;
  137. }
  138. /**
  139. * Removes a client. Called by each `Socket`.
  140. *
  141. * @private
  142. */
  143. _remove(socket) {
  144. if (this.sockets.has(socket.id)) {
  145. this.sockets.delete(socket.id);
  146. }
  147. else {
  148. debug("ignoring remove for %s", socket.id);
  149. }
  150. }
  151. /**
  152. * Emits to all clients.
  153. *
  154. * @return {Boolean} Always true
  155. * @public
  156. */
  157. emit(ev, ...args) {
  158. if (socket_1.RESERVED_EVENTS.has(ev)) {
  159. throw new Error(`"${ev}" is a reserved event name`);
  160. }
  161. // set up packet object
  162. args.unshift(ev);
  163. const packet = {
  164. type: socket_io_parser_1.PacketType.EVENT,
  165. data: args
  166. };
  167. if ("function" == typeof args[args.length - 1]) {
  168. throw new Error("Callbacks are not supported when broadcasting");
  169. }
  170. const rooms = new Set(this._rooms);
  171. const flags = Object.assign({}, this._flags);
  172. // reset flags
  173. this._rooms.clear();
  174. this._flags = {};
  175. this.adapter.broadcast(packet, {
  176. rooms: rooms,
  177. flags: flags
  178. });
  179. return true;
  180. }
  181. /**
  182. * Sends a `message` event to all clients.
  183. *
  184. * @return {Namespace} self
  185. * @public
  186. */
  187. send(...args) {
  188. args.unshift("message");
  189. this.emit.apply(this, args);
  190. return this;
  191. }
  192. /**
  193. * Sends a `message` event to all clients.
  194. *
  195. * @return {Namespace} self
  196. * @public
  197. */
  198. write(...args) {
  199. args.unshift("message");
  200. this.emit.apply(this, args);
  201. return this;
  202. }
  203. /**
  204. * Gets a list of clients.
  205. *
  206. * @return {Namespace} self
  207. * @public
  208. */
  209. allSockets() {
  210. if (!this.adapter) {
  211. throw new Error("No adapter for this namespace, are you trying to get the list of clients of a dynamic namespace?");
  212. }
  213. const rooms = new Set(this._rooms);
  214. this._rooms.clear();
  215. return this.adapter.sockets(rooms);
  216. }
  217. /**
  218. * Sets the compress flag.
  219. *
  220. * @param {Boolean} compress - if `true`, compresses the sending data
  221. * @return {Namespace} self
  222. * @public
  223. */
  224. compress(compress) {
  225. this._flags.compress = compress;
  226. return this;
  227. }
  228. /**
  229. * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to
  230. * receive messages (because of network slowness or other issues, or because they’re connected through long polling
  231. * and is in the middle of a request-response cycle).
  232. *
  233. * @return {Namespace} self
  234. * @public
  235. */
  236. get volatile() {
  237. this._flags.volatile = true;
  238. return this;
  239. }
  240. /**
  241. * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node.
  242. *
  243. * @return {Namespace} self
  244. * @public
  245. */
  246. get local() {
  247. this._flags.local = true;
  248. return this;
  249. }
  250. }
  251. exports.Namespace = Namespace;