From ebb0575fa82af8a94d371f09fea62c3a521c3b8e Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Tue, 13 Oct 2020 23:36:21 +0200 Subject: [PATCH] chore(release): 3.0.0-rc1 Diff: https://github.com/socketio/socket.io/compare/2.3.0...3.0.0-rc1 --- .gitignore | 1 + CHANGELOG.md | 81 +++++++ dist/client.d.ts | 93 -------- dist/client.js | 224 ------------------ dist/index.d.ts | 299 ------------------------ dist/index.js | 453 ----------------------------------- dist/namespace.d.ts | 128 ---------- dist/namespace.js | 254 -------------------- dist/parent-namespace.d.ts | 9 - dist/parent-namespace.js | 36 --- dist/socket.d.ts | 258 -------------------- dist/socket.js | 467 ------------------------------------- package.json | 9 +- 13 files changed, 87 insertions(+), 2225 deletions(-) create mode 100644 CHANGELOG.md delete mode 100644 dist/client.d.ts delete mode 100644 dist/client.js delete mode 100644 dist/index.d.ts delete mode 100644 dist/index.js delete mode 100644 dist/namespace.d.ts delete mode 100644 dist/namespace.js delete mode 100644 dist/parent-namespace.d.ts delete mode 100644 dist/parent-namespace.js delete mode 100644 dist/socket.d.ts delete mode 100644 dist/socket.js diff --git a/.gitignore b/.gitignore index 9b8b77d61a..339440ff84 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ node_modules coverage .idea .nyc_output +dist/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..7b42f3a7fd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,81 @@ +# [3.0.0-rc1](https://github.com/socketio/socket.io/compare/2.3.0...3.0.0-rc1) (2020-10-13) + + +### Features + +* add ES6 module export ([8b6b100](https://github.com/socketio/socket.io/commit/8b6b100c284ccce7d85e55659e3397f533916847)) +* do not reuse the Engine.IO id ([2875d2c](https://github.com/socketio/socket.io/commit/2875d2cfdfa463e64cb520099749f543bbc4eb15)) +* remove Server#set() method ([029f478](https://github.com/socketio/socket.io/commit/029f478992f59b1eb5226453db46363a570eea46)) +* remove Socket#rooms object ([1507b41](https://github.com/socketio/socket.io/commit/1507b416d584381554d1ed23c9aaf3b650540071)) +* remove the 'origins' option ([a8c0600](https://github.com/socketio/socket.io/commit/a8c06006098b512ba1b8b8df82777349db486f41)) +* remove the implicit connection to the default namespace ([3289f7e](https://github.com/socketio/socket.io/commit/3289f7ec376e9ec88c2f90e2735c8ca8d01c0e97)) +* throw upon reserved event names ([4bd5b23](https://github.com/socketio/socket.io/commit/4bd5b2339a66a5a675e20f689fff2e70ff12d236)) + + +### BREAKING CHANGES + +* the 'origins' option is removed + +Before: + +```js +new Server(3000, { + origins: ["https://example.com"] +}); +``` + +The 'origins' option was used in the allowRequest method, in order to +determine whether the request should pass or not. And the Engine.IO +server would implicitly add the necessary Access-Control-Allow-xxx +headers. + +After: + +```js +new Server(3000, { + cors: { + origin: "https://example.com", + methods: ["GET", "POST"], + allowedHeaders: ["content-type"] + } +}); +``` + +The already existing 'allowRequest' option can be used for validation: + +```js +new Server(3000, { + allowRequest: (req, callback) => { + callback(null, req.headers.referer.startsWith("https://example.com")); + } +}); +``` + +* Socket#rooms is now a Set instead of an object + +* Namespace#connected is now a Map instead of an object + +* there is no more implicit connection to the default namespace: + +```js +// client-side +const socket = io("/admin"); + +// server-side +io.on("connect", socket => { + // not triggered anymore +}) + +io.use((socket, next) => { + // not triggered anymore +}); + +io.of("/admin").use((socket, next) => { + // triggered +}); +``` + +* the Server#set() method was removed + +This method was kept for backward-compatibility with pre-1.0 versions. + diff --git a/dist/client.d.ts b/dist/client.d.ts deleted file mode 100644 index 2a42798592..0000000000 --- a/dist/client.d.ts +++ /dev/null @@ -1,93 +0,0 @@ -/// -import { IncomingMessage } from "http"; -import { Server } from "./index"; -import { Socket } from "./socket"; -export declare class Client { - readonly conn: any; - /** @package */ - readonly id: string; - private readonly server; - private readonly encoder; - private readonly decoder; - private sockets; - private nsps; - /** - * Client constructor. - * - * @param {Server} server instance - * @param {Socket} conn - * @package - */ - constructor(server: Server, conn: any); - /** - * @return the reference to the request that originated the Engine.IO connection - */ - get request(): IncomingMessage; - /** - * Sets up event listeners. - */ - private setup; - /** - * Connects a client to a namespace. - * - * @param {String} name - the namespace - * @param {Object} auth - the auth parameters - * @package - */ - connect(name: string, auth?: object): void; - /** - * Connects a client to a namespace. - * - * @param {String} name - the namespace - * @param {Object} auth - the auth parameters - */ - private doConnect; - /** - * Disconnects from all namespaces and closes transport. - * - * @package - */ - disconnect(): void; - /** - * Removes a socket. Called by each `Socket`. - * - * @package - */ - remove(socket: Socket): void; - /** - * Closes the underlying connection. - */ - private close; - /** - * Writes a packet to the transport. - * - * @param {Object} packet object - * @param {Object} opts - * @package - */ - packet(packet: any, opts?: any): void; - /** - * Called with incoming transport data. - */ - private ondata; - /** - * Called when parser fully decodes a packet. - */ - private ondecoded; - /** - * Handles an error. - * - * @param {Object} err object - */ - private onerror; - /** - * Called upon transport close. - * - * @param reason - */ - private onclose; - /** - * Cleans up event listeners. - */ - private destroy; -} diff --git a/dist/client.js b/dist/client.js deleted file mode 100644 index a37aebb0ca..0000000000 --- a/dist/client.js +++ /dev/null @@ -1,224 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Client = void 0; -const socket_io_parser_1 = require("socket.io-parser"); -const debugModule = require("debug"); -const debug = debugModule("socket.io:client"); -class Client { - /** - * Client constructor. - * - * @param {Server} server instance - * @param {Socket} conn - * @package - */ - constructor(server, conn) { - this.sockets = new Map(); - this.nsps = new Map(); - this.server = server; - this.conn = conn; - this.encoder = server.encoder; - this.decoder = new server.parser.Decoder(); - this.id = conn.id; - this.setup(); - } - /** - * @return the reference to the request that originated the Engine.IO connection - */ - get request() { - return this.conn.request; - } - /** - * Sets up event listeners. - */ - setup() { - this.onclose = this.onclose.bind(this); - this.ondata = this.ondata.bind(this); - this.onerror = this.onerror.bind(this); - this.ondecoded = this.ondecoded.bind(this); - // @ts-ignore - this.decoder.on("decoded", this.ondecoded); - this.conn.on("data", this.ondata); - this.conn.on("error", this.onerror); - this.conn.on("close", this.onclose); - } - /** - * Connects a client to a namespace. - * - * @param {String} name - the namespace - * @param {Object} auth - the auth parameters - * @package - */ - connect(name, auth = {}) { - if (this.server.nsps.has(name)) { - debug("connecting to namespace %s", name); - return this.doConnect(name, auth); - } - this.server.checkNamespace(name, auth, dynamicNsp => { - if (dynamicNsp) { - debug("dynamic namespace %s was created", dynamicNsp.name); - this.doConnect(name, auth); - } - else { - debug("creation of namespace %s was denied", name); - this.packet({ - type: socket_io_parser_1.PacketType.ERROR, - nsp: name, - data: "Invalid namespace" - }); - } - }); - } - /** - * Connects a client to a namespace. - * - * @param {String} name - the namespace - * @param {Object} auth - the auth parameters - */ - doConnect(name, auth) { - const nsp = this.server.of(name); - const socket = nsp.add(this, auth, () => { - this.sockets.set(socket.id, socket); - this.nsps.set(nsp.name, socket); - }); - } - /** - * Disconnects from all namespaces and closes transport. - * - * @package - */ - disconnect() { - for (const socket of this.sockets.values()) { - socket.disconnect(); - } - this.sockets.clear(); - this.close(); - } - /** - * Removes a socket. Called by each `Socket`. - * - * @package - */ - remove(socket) { - if (this.sockets.has(socket.id)) { - const nsp = this.sockets.get(socket.id).nsp.name; - this.sockets.delete(socket.id); - this.nsps.delete(nsp); - } - else { - debug("ignoring remove for %s", socket.id); - } - } - /** - * Closes the underlying connection. - */ - close() { - if ("open" == this.conn.readyState) { - debug("forcing transport close"); - this.conn.close(); - this.onclose("forced server close"); - } - } - /** - * Writes a packet to the transport. - * - * @param {Object} packet object - * @param {Object} opts - * @package - */ - packet(packet, opts) { - opts = opts || {}; - const self = this; - // this writes to the actual connection - function writeToEngine(encodedPackets) { - if (opts.volatile && !self.conn.transport.writable) - return; - for (let i = 0; i < encodedPackets.length; i++) { - self.conn.write(encodedPackets[i], { compress: opts.compress }); - } - } - if ("open" == this.conn.readyState) { - debug("writing packet %j", packet); - if (!opts.preEncoded) { - // not broadcasting, need to encode - writeToEngine(this.encoder.encode(packet)); // encode, then write results to engine - } - else { - // a broadcast pre-encodes a packet - writeToEngine(packet); - } - } - else { - debug("ignoring packet write %j", packet); - } - } - /** - * Called with incoming transport data. - */ - ondata(data) { - // try/catch is needed for protocol violations (GH-1880) - try { - this.decoder.add(data); - } - catch (e) { - this.onerror(e); - } - } - /** - * Called when parser fully decodes a packet. - */ - ondecoded(packet) { - if (socket_io_parser_1.PacketType.CONNECT == packet.type) { - this.connect(packet.nsp, packet.data); - } - else { - const socket = this.nsps.get(packet.nsp); - if (socket) { - process.nextTick(function () { - socket.onpacket(packet); - }); - } - else { - debug("no socket for namespace %s", packet.nsp); - } - } - } - /** - * Handles an error. - * - * @param {Object} err object - */ - onerror(err) { - for (const socket of this.sockets.values()) { - socket.onerror(err); - } - this.conn.close(); - } - /** - * Called upon transport close. - * - * @param reason - */ - onclose(reason) { - debug("client close with reason %s", reason); - // ignore a potential subsequent `close` event - this.destroy(); - // `nsps` and `sockets` are cleaned up seamlessly - for (const socket of this.sockets.values()) { - socket.onclose(reason); - } - this.sockets.clear(); - this.decoder.destroy(); // clean up decoder - } - /** - * Cleans up event listeners. - */ - destroy() { - this.conn.removeListener("data", this.ondata); - this.conn.removeListener("error", this.onerror); - this.conn.removeListener("close", this.onclose); - // @ts-ignore - this.decoder.removeListener("decoded", this.ondecoded); - } -} -exports.Client = Client; diff --git a/dist/index.d.ts b/dist/index.d.ts deleted file mode 100644 index a050869a63..0000000000 --- a/dist/index.d.ts +++ /dev/null @@ -1,299 +0,0 @@ -/// -import http from "http"; -import { EventEmitter } from "events"; -import { Namespace } from "./namespace"; -import { Room, SocketId } from "socket.io-adapter"; -import { Encoder } from "socket.io-parser"; -import { Socket } from "./socket"; -import { CookieSerializeOptions } from "cookie"; -import { CorsOptions } from "cors"; -declare type Transport = "polling" | "websocket"; -interface EngineOptions { - /** - * how many ms without a pong packet to consider the connection closed (5000) - */ - pingTimeout: number; - /** - * how many ms before sending a new ping packet (25000) - */ - pingInterval: number; - /** - * how many ms before an uncompleted transport upgrade is cancelled (10000) - */ - upgradeTimeout: number; - /** - * how many bytes or characters a message can be, before closing the session (to avoid DoS). Default value is 1E5. - */ - maxHttpBufferSize: number; - /** - * A function that receives a given handshake or upgrade request as its first parameter, - * and can decide whether to continue or not. The second argument is a function that needs - * to be called with the decided information: fn(err, success), where success is a boolean - * value where false means that the request is rejected, and err is an error code. - */ - allowRequest: (req: http.IncomingMessage, fn: (err: string | null | undefined, success: boolean) => void) => void; - /** - * to allow connections to (['polling', 'websocket']) - */ - transports: Transport[]; - /** - * whether to allow transport upgrades (true) - */ - allowUpgrades: boolean; - /** - * parameters of the WebSocket permessage-deflate extension (see ws module api docs). Set to false to disable. (false) - */ - perMessageDeflate: boolean | object; - /** - * parameters of the http compression for the polling transports (see zlib api docs). Set to false to disable. (true) - */ - httpCompression: boolean | object; - /** - * what WebSocket server implementation to use. Specified module must - * conform to the ws interface (see ws module api docs). Default value is ws. - * An alternative c++ addon is also available by installing uws module. - */ - wsEngine: string; - /** - * an optional packet which will be concatenated to the handshake packet emitted by Engine.IO. - */ - initialPacket: any; - /** - * configuration of the cookie that contains the client sid to send as part of handshake response headers. This cookie - * might be used for sticky-session. Defaults to not sending any cookie (false) - */ - cookie: CookieSerializeOptions | boolean; - /** - * the options that will be forwarded to the cors module - */ - cors: CorsOptions; -} -interface AttachOptions { - /** - * name of the path to capture (/engine.io). - */ - path: string; - /** - * destroy unhandled upgrade requests (true) - */ - destroyUpgrade: boolean; - /** - * milliseconds after which unhandled requests are ended (1000) - */ - destroyUpgradeTimeout: number; -} -interface EngineAttachOptions extends EngineOptions, AttachOptions { -} -interface ServerOptions extends EngineAttachOptions { - /** - * name of the path to capture (/socket.io) - */ - path: string; - /** - * whether to serve the client files (true) - */ - serveClient: boolean; - /** - * the adapter to use. Defaults to an instance of the Adapter that ships with socket.io which is memory based. - */ - adapter: any; - /** - * the parser to use. Defaults to an instance of the Parser that ships with socket.io. - */ - parser: any; -} -export declare class Server extends EventEmitter { - readonly sockets: Namespace; - /** @package */ - readonly parser: any; - /** @package */ - readonly encoder: Encoder; - nsps: Map; - private parentNsps; - private _adapter; - private _serveClient; - private eio; - private engine; - private _path; - private httpServer; - /** - * Server constructor. - * - * @param {http.Server|Number|Object} srv http server, port or options - * @param {Object} [opts] - */ - constructor(opts?: Partial); - constructor(srv: http.Server, opts?: Partial); - constructor(srv: number, opts?: Partial); - /** - * Sets/gets whether client code is being served. - * - * @param {Boolean} v - whether to serve client code - * @return {Server|Boolean} self when setting or value when getting - */ - serveClient(v?: boolean): boolean | this; - /** - * Executes the middleware for an incoming namespace not already created on the server. - * - * @param {String} name - name of incoming namespace - * @param {Object} auth - the auth parameters - * @param {Function} fn - callback - * - * @package - */ - checkNamespace(name: string, auth: object, fn: (nsp: Namespace | boolean) => void): void; - /** - * Sets the client serving path. - * - * @param {String} v pathname - * @return {Server|String} self when setting or value when getting - */ - path(v?: string): string | this; - /** - * Sets the adapter for rooms. - * - * @param {Adapter} v pathname - * @return {Server|Adapter} self when setting or value when getting - */ - adapter(v: any): any; - /** - * Attaches socket.io to a server or port. - * - * @param {http.Server|Number} srv - server or port - * @param {Object} opts - options passed to engine.io - * @return {Server} self - */ - listen(srv: http.Server, opts?: Partial): Server; - listen(srv: number, opts?: Partial): Server; - /** - * Attaches socket.io to a server or port. - * - * @param {http.Server|Number} srv - server or port - * @param {Object} opts - options passed to engine.io - * @return {Server} self - */ - attach(srv: http.Server, opts?: Partial): Server; - attach(port: number, opts?: Partial): Server; - /** - * Initialize engine - * - * @param srv - the server to attach to - * @param opts - options passed to engine.io - */ - private initEngine; - /** - * Attaches the static file serving. - * - * @param {Function|http.Server} srv http server - */ - private attachServe; - /** - * Handles a request serving `/socket.io.js` - * - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - */ - private serve; - /** - * Handles a request serving `/socket.io.js.map` - * - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - */ - private serveMap; - /** - * Binds socket.io to an engine.io instance. - * - * @param {engine.Server} engine engine.io (or compatible) server - * @return {Server} self - */ - bind(engine: any): Server; - /** - * Called with each incoming transport connection. - * - * @param {engine.Socket} conn - * @return {Server} self - */ - private onconnection; - /** - * Looks up a namespace. - * - * @param {String|RegExp|Function} name nsp name - * @param {Function} [fn] optional, nsp `connection` ev handler - */ - of(name: string | RegExp | ((name: string, query: object, fn: (err: Error, success: boolean) => void) => void), fn?: (socket: Socket) => void): Namespace; - /** - * Closes server connection - * - * @param {Function} [fn] optional, called as `fn([err])` on error OR all conns closed - */ - close(fn?: (err?: Error) => void): void; - /** - * Sets up namespace middleware. - * - * @return {Server} self - * @public - */ - use(fn: (socket: Socket, next: (err?: Error) => void) => void): Server; - /** - * Targets a room when emitting. - * - * @param {String} name - * @return {Server} self - * @public - */ - to(name: Room): Server; - /** - * Targets a room when emitting. - * - * @param {String} name - * @return {Server} self - * @public - */ - in(name: Room): Server; - /** - * Sends a `message` event to all clients. - * - * @return {Namespace} self - */ - send(...args: any[]): Server; - /** - * Sends a `message` event to all clients. - * - * @return {Namespace} self - */ - write(...args: any[]): Server; - /** - * Gets a list of socket ids. - */ - allSockets(): Promise>; - /** - * Sets the compress flag. - * - * @param {Boolean} compress - if `true`, compresses the sending data - * @return {Server} self - */ - compress(compress: boolean): Server; - /** - * Sets the binary flag - * - * @param {Boolean} binary - encode as if it has binary data if `true`, Encode as if it doesnt have binary data if `false` - * @return {Server} self - */ - binary(binary: boolean): Server; - /** - * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to - * receive messages (because of network slowness or other issues, or because they’re connected through long polling - * and is in the middle of a request-response cycle). - * - * @return {Server} self - */ - get volatile(): Server; - /** - * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node. - * - * @return {Server} self - */ - get local(): Server; -} -export {}; diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index d4c8d4cf02..0000000000 --- a/dist/index.js +++ /dev/null @@ -1,453 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Server = void 0; -const http_1 = __importDefault(require("http")); -const fs_1 = require("fs"); -const path_1 = __importDefault(require("path")); -const engine_io_1 = __importDefault(require("engine.io")); -const client_1 = require("./client"); -const events_1 = require("events"); -const namespace_1 = require("./namespace"); -const parent_namespace_1 = require("./parent-namespace"); -const socket_io_adapter_1 = require("socket.io-adapter"); -const parser = __importStar(require("socket.io-parser")); -const debug_1 = __importDefault(require("debug")); -const debug = debug_1.default("socket.io:server"); -const clientVersion = require("socket.io-client/package.json").version; -/** - * Socket.IO client source. - */ -let clientSource = undefined; -let clientSourceMap = undefined; -class Server extends events_1.EventEmitter { - constructor(srv, opts = {}) { - super(); - this.nsps = new Map(); - this.parentNsps = new Map(); - if ("object" == typeof srv && srv instanceof Object && !srv.listen) { - opts = srv; - srv = null; - } - this.path(opts.path || "/socket.io"); - this.serveClient(false !== opts.serveClient); - this.parser = opts.parser || parser; - this.encoder = new this.parser.Encoder(); - this.adapter(opts.adapter || socket_io_adapter_1.Adapter); - this.sockets = this.of("/"); - if (srv) - this.attach(srv, opts); - } - /** - * Sets/gets whether client code is being served. - * - * @param {Boolean} v - whether to serve client code - * @return {Server|Boolean} self when setting or value when getting - */ - serveClient(v) { - if (!arguments.length) - return this._serveClient; - this._serveClient = v; - const resolvePath = function (file) { - const filepath = path_1.default.resolve(__dirname, "./../../", file); - if (fs_1.existsSync(filepath)) { - return filepath; - } - return require.resolve(file); - }; - if (v && !clientSource) { - clientSource = fs_1.readFileSync(resolvePath("socket.io-client/dist/socket.io.js"), "utf-8"); - try { - clientSourceMap = fs_1.readFileSync(resolvePath("socket.io-client/dist/socket.io.js.map"), "utf-8"); - } - catch (err) { - debug("could not load sourcemap file"); - } - } - return this; - } - /** - * Executes the middleware for an incoming namespace not already created on the server. - * - * @param {String} name - name of incoming namespace - * @param {Object} auth - the auth parameters - * @param {Function} fn - callback - * - * @package - */ - checkNamespace(name, auth, fn) { - if (this.parentNsps.size === 0) - return fn(false); - const keysIterator = this.parentNsps.keys(); - const run = () => { - let nextFn = keysIterator.next(); - if (nextFn.done) { - return fn(false); - } - nextFn.value(name, auth, (err, allow) => { - if (err || !allow) { - run(); - } - else { - fn(this.parentNsps.get(nextFn.value).createChild(name)); - } - }); - }; - run(); - } - /** - * Sets the client serving path. - * - * @param {String} v pathname - * @return {Server|String} self when setting or value when getting - */ - path(v) { - if (!arguments.length) - return this._path; - this._path = v.replace(/\/$/, ""); - return this; - } - /** - * Sets the adapter for rooms. - * - * @param {Adapter} v pathname - * @return {Server|Adapter} self when setting or value when getting - */ - adapter(v) { - if (!arguments.length) - return this._adapter; - this._adapter = v; - for (const nsp of this.nsps.values()) { - nsp.initAdapter(); - } - return this; - } - listen(srv, opts = {}) { - return this.attach(srv, opts); - } - attach(srv, opts = {}) { - if ("function" == typeof srv) { - const msg = "You are trying to attach socket.io to an express " + - "request handler function. Please pass a http.Server instance."; - throw new Error(msg); - } - // handle a port as a string - if (Number(srv) == srv) { - srv = Number(srv); - } - if ("number" == typeof srv) { - debug("creating http server and binding to %d", srv); - const port = srv; - srv = http_1.default.createServer((req, res) => { - res.writeHead(404); - res.end(); - }); - srv.listen(port); - } - // set engine.io path to `/socket.io` - opts.path = opts.path || this._path; - this.initEngine(srv, opts); - return this; - } - /** - * Initialize engine - * - * @param srv - the server to attach to - * @param opts - options passed to engine.io - */ - initEngine(srv, opts) { - // initialize engine - debug("creating engine.io instance with opts %j", opts); - this.eio = engine_io_1.default.attach(srv, opts); - // attach static file serving - if (this._serveClient) - this.attachServe(srv); - // Export http server - this.httpServer = srv; - // bind to engine events - this.bind(this.eio); - } - /** - * Attaches the static file serving. - * - * @param {Function|http.Server} srv http server - */ - attachServe(srv) { - debug("attaching client serving req handler"); - const url = this._path + "/socket.io.js"; - const urlMap = this._path + "/socket.io.js.map"; - const evs = srv.listeners("request").slice(0); - const self = this; - srv.removeAllListeners("request"); - srv.on("request", function (req, res) { - if (0 === req.url.indexOf(urlMap)) { - self.serveMap(req, res); - } - else if (0 === req.url.indexOf(url)) { - self.serve(req, res); - } - else { - for (let i = 0; i < evs.length; i++) { - evs[i].call(srv, req, res); - } - } - }); - } - /** - * Handles a request serving `/socket.io.js` - * - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - */ - serve(req, res) { - // Per the standard, ETags must be quoted: - // https://tools.ietf.org/html/rfc7232#section-2.3 - const expectedEtag = '"' + clientVersion + '"'; - const etag = req.headers["if-none-match"]; - if (etag) { - if (expectedEtag == etag) { - debug("serve client 304"); - res.writeHead(304); - res.end(); - return; - } - } - debug("serve client source"); - res.setHeader("Cache-Control", "public, max-age=0"); - res.setHeader("Content-Type", "application/javascript"); - res.setHeader("ETag", expectedEtag); - res.writeHead(200); - res.end(clientSource); - } - /** - * Handles a request serving `/socket.io.js.map` - * - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - */ - serveMap(req, res) { - // Per the standard, ETags must be quoted: - // https://tools.ietf.org/html/rfc7232#section-2.3 - const expectedEtag = '"' + clientVersion + '"'; - const etag = req.headers["if-none-match"]; - if (etag) { - if (expectedEtag == etag) { - debug("serve client 304"); - res.writeHead(304); - res.end(); - return; - } - } - debug("serve client sourcemap"); - res.setHeader("Content-Type", "application/json"); - res.setHeader("ETag", expectedEtag); - res.writeHead(200); - res.end(clientSourceMap); - } - /** - * Binds socket.io to an engine.io instance. - * - * @param {engine.Server} engine engine.io (or compatible) server - * @return {Server} self - */ - bind(engine) { - this.engine = engine; - this.engine.on("connection", this.onconnection.bind(this)); - return this; - } - /** - * Called with each incoming transport connection. - * - * @param {engine.Socket} conn - * @return {Server} self - */ - onconnection(conn) { - debug("incoming connection with id %s", conn.id); - new client_1.Client(this, conn); - return this; - } - /** - * Looks up a namespace. - * - * @param {String|RegExp|Function} name nsp name - * @param {Function} [fn] optional, nsp `connection` ev handler - */ - of(name, fn) { - if (typeof name === "function" || name instanceof RegExp) { - const parentNsp = new parent_namespace_1.ParentNamespace(this); - debug("initializing parent namespace %s", parentNsp.name); - if (typeof name === "function") { - this.parentNsps.set(name, parentNsp); - } - else { - this.parentNsps.set((nsp, conn, next) => next(null, name.test(nsp)), parentNsp); - } - if (fn) { - // @ts-ignore - parentNsp.on("connect", fn); - } - return parentNsp; - } - if (String(name)[0] !== "/") - name = "/" + name; - let nsp = this.nsps.get(name); - if (!nsp) { - debug("initializing namespace %s", name); - nsp = new namespace_1.Namespace(this, name); - this.nsps.set(name, nsp); - } - if (fn) - nsp.on("connect", fn); - return nsp; - } - /** - * Closes server connection - * - * @param {Function} [fn] optional, called as `fn([err])` on error OR all conns closed - */ - close(fn) { - for (const socket of this.sockets.sockets.values()) { - socket.onclose("server shutting down"); - } - this.engine.close(); - if (this.httpServer) { - this.httpServer.close(fn); - } - else { - fn && fn(); - } - } - /** - * Sets up namespace middleware. - * - * @return {Server} self - * @public - */ - use(fn) { - this.sockets.use(fn); - return this; - } - /** - * Targets a room when emitting. - * - * @param {String} name - * @return {Server} self - * @public - */ - to(name) { - this.sockets.to(name); - return this; - } - /** - * Targets a room when emitting. - * - * @param {String} name - * @return {Server} self - * @public - */ - in(name) { - this.sockets.in(name); - return this; - } - /** - * Sends a `message` event to all clients. - * - * @return {Namespace} self - */ - send(...args) { - args.unshift("message"); - this.sockets.emit.apply(this.sockets, args); - return this; - } - /** - * Sends a `message` event to all clients. - * - * @return {Namespace} self - */ - write(...args) { - args.unshift("message"); - this.sockets.emit.apply(this.sockets, args); - return this; - } - /** - * Gets a list of socket ids. - */ - allSockets() { - return this.sockets.allSockets(); - } - /** - * Sets the compress flag. - * - * @param {Boolean} compress - if `true`, compresses the sending data - * @return {Server} self - */ - compress(compress) { - this.sockets.compress(compress); - return this; - } - /** - * Sets the binary flag - * - * @param {Boolean} binary - encode as if it has binary data if `true`, Encode as if it doesnt have binary data if `false` - * @return {Server} self - */ - binary(binary) { - this.sockets.binary(binary); - return this; - } - /** - * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to - * receive messages (because of network slowness or other issues, or because they’re connected through long polling - * and is in the middle of a request-response cycle). - * - * @return {Server} self - */ - get volatile() { - this.sockets.volatile; - return this; - } - /** - * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node. - * - * @return {Server} self - */ - get local() { - this.sockets.local; - return this; - } -} -exports.Server = Server; -/** - * Expose main namespace (/). - */ -const emitterMethods = Object.keys(events_1.EventEmitter.prototype).filter(function (key) { - return typeof events_1.EventEmitter.prototype[key] === "function"; -}); -emitterMethods.forEach(function (fn) { - Server.prototype[fn] = function () { - return this.sockets[fn].apply(this.sockets, arguments); - }; -}); -module.exports = (srv, opts) => new Server(srv, opts); -module.exports.Server = Server; diff --git a/dist/namespace.d.ts b/dist/namespace.d.ts deleted file mode 100644 index 35561c808b..0000000000 --- a/dist/namespace.d.ts +++ /dev/null @@ -1,128 +0,0 @@ -/// -import { Socket } from "./socket"; -import { Server } from "./index"; -import { EventEmitter } from "events"; -import { Adapter, Room, SocketId } from "socket.io-adapter"; -export declare class Namespace extends EventEmitter { - readonly name: string; - readonly connected: Map; - adapter: Adapter; - /** @package */ - readonly server: any; - /** @package */ - fns: Array<(socket: Socket, next: (err: Error) => void) => void>; - /** @package */ - rooms: Set; - /** @package */ - flags: any; - /** @package */ - ids: number; - /** @package */ - sockets: Map; - /** - * Namespace constructor. - * - * @param {Server} server instance - * @param {string} name - */ - constructor(server: Server, name: string); - /** - * Initializes the `Adapter` for this nsp. - * Run upon changing adapter by `Server#adapter` - * in addition to the constructor. - * - * @package - */ - initAdapter(): void; - /** - * Sets up namespace middleware. - * - * @return {Namespace} self - */ - use(fn: (socket: Socket, next: (err?: Error) => void) => void): Namespace; - /** - * Executes the middleware for an incoming client. - * - * @param {Socket} socket - the socket that will get added - * @param {Function} fn - last fn call in the middleware - */ - private run; - /** - * Targets a room when emitting. - * - * @param {String} name - * @return {Namespace} self - */ - to(name: Room): Namespace; - /** - * Targets a room when emitting. - * - * @param {String} name - * @return {Namespace} self - */ - in(name: Room): Namespace; - /** - * Adds a new client. - * - * @return {Socket} - */ - private add; - /** - * Removes a client. Called by each `Socket`. - * - * @package - */ - remove(socket: Socket): void; - /** - * Emits to all clients. - * - * @return {Namespace} self - */ - emit(ev: string, ...args: any[]): Namespace; - /** - * Sends a `message` event to all clients. - * - * @return {Namespace} self - */ - send(...args: any[]): Namespace; - /** - * Sends a `message` event to all clients. - * - * @return {Namespace} self - */ - write(...args: any[]): Namespace; - /** - * Gets a list of clients. - * - * @return {Namespace} self - */ - allSockets(): Promise>; - /** - * Sets the compress flag. - * - * @param {Boolean} compress - if `true`, compresses the sending data - * @return {Namespace} self - */ - compress(compress: boolean): Namespace; - /** - * Sets the binary flag - * - * @param {Boolean} binary - encode as if it has binary data if `true`, Encode as if it doesnt have binary data if `false` - * @return {Namespace} self - */ - binary(binary: boolean): Namespace; - /** - * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to - * receive messages (because of network slowness or other issues, or because they’re connected through long polling - * and is in the middle of a request-response cycle). - * - * @return {Namespace} self - */ - get volatile(): Namespace; - /** - * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node. - * - * @return {Namespace} self - */ - get local(): Namespace; -} diff --git a/dist/namespace.js b/dist/namespace.js deleted file mode 100644 index 7185862f7d..0000000000 --- a/dist/namespace.js +++ /dev/null @@ -1,254 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Namespace = void 0; -const socket_1 = require("./socket"); -const events_1 = require("events"); -const socket_io_parser_1 = require("socket.io-parser"); -const has_binary2_1 = __importDefault(require("has-binary2")); -const debug_1 = __importDefault(require("debug")); -const debug = debug_1.default("socket.io:namespace"); -class Namespace extends events_1.EventEmitter { - /** - * Namespace constructor. - * - * @param {Server} server instance - * @param {string} name - */ - constructor(server, name) { - super(); - this.connected = new Map(); - /** @package */ - this.fns = []; - /** @package */ - this.rooms = new Set(); - /** @package */ - this.flags = {}; - /** @package */ - this.ids = 0; - /** @package */ - this.sockets = new Map(); - this.server = server; - this.name = name; - this.initAdapter(); - } - /** - * Initializes the `Adapter` for this nsp. - * Run upon changing adapter by `Server#adapter` - * in addition to the constructor. - * - * @package - */ - initAdapter() { - this.adapter = new (this.server.adapter())(this); - } - /** - * Sets up namespace middleware. - * - * @return {Namespace} self - */ - use(fn) { - this.fns.push(fn); - return this; - } - /** - * Executes the middleware for an incoming client. - * - * @param {Socket} socket - the socket that will get added - * @param {Function} fn - last fn call in the middleware - */ - run(socket, fn) { - const fns = this.fns.slice(0); - if (!fns.length) - return fn(null); - function run(i) { - fns[i](socket, function (err) { - // upon error, short-circuit - if (err) - return fn(err); - // if no middleware left, summon callback - if (!fns[i + 1]) - return fn(null); - // go on to next - run(i + 1); - }); - } - run(0); - } - /** - * Targets a room when emitting. - * - * @param {String} name - * @return {Namespace} self - */ - to(name) { - this.rooms.add(name); - return this; - } - /** - * Targets a room when emitting. - * - * @param {String} name - * @return {Namespace} self - */ - in(name) { - this.rooms.add(name); - return this; - } - /** - * Adds a new client. - * - * @return {Socket} - */ - add(client, query, fn) { - debug("adding socket to nsp %s", this.name); - const socket = new socket_1.Socket(this, client, query); - this.run(socket, err => { - process.nextTick(() => { - if ("open" == client.conn.readyState) { - if (err) - return socket.error(err.message); - // track socket - this.sockets.set(socket.id, socket); - // it's paramount that the internal `onconnect` logic - // fires before user-set events to prevent state order - // violations (such as a disconnection before the connection - // logic is complete) - socket.onconnect(); - if (fn) - fn(); - // fire user-set events - super.emit("connect", socket); - super.emit("connection", socket); - } - else { - debug("next called after client was closed - ignoring socket"); - } - }); - }); - return socket; - } - /** - * Removes a client. Called by each `Socket`. - * - * @package - */ - remove(socket) { - if (this.sockets.has(socket.id)) { - this.sockets.delete(socket.id); - } - else { - debug("ignoring remove for %s", socket.id); - } - } - /** - * Emits to all clients. - * - * @return {Namespace} self - */ - // @ts-ignore - emit(ev, ...args) { - if (socket_1.RESERVED_EVENTS.has(ev)) { - throw new Error(`"${ev}" is a reserved event name`); - } - // set up packet object - args.unshift(ev); - const packet = { - type: (this.flags.binary !== undefined - ? this.flags.binary - : has_binary2_1.default(args)) - ? socket_io_parser_1.PacketType.BINARY_EVENT - : socket_io_parser_1.PacketType.EVENT, - data: args - }; - if ("function" == typeof args[args.length - 1]) { - throw new Error("Callbacks are not supported when broadcasting"); - } - const rooms = new Set(this.rooms); - const flags = Object.assign({}, this.flags); - // reset flags - this.rooms.clear(); - this.flags = {}; - this.adapter.broadcast(packet, { - rooms: rooms, - flags: flags - }); - return this; - } - /** - * Sends a `message` event to all clients. - * - * @return {Namespace} self - */ - send(...args) { - args.unshift("message"); - this.emit.apply(this, args); - return this; - } - /** - * Sends a `message` event to all clients. - * - * @return {Namespace} self - */ - write(...args) { - args.unshift("message"); - this.emit.apply(this, args); - return this; - } - /** - * Gets a list of clients. - * - * @return {Namespace} self - */ - allSockets() { - if (!this.adapter) { - throw new Error("No adapter for this namespace, are you trying to get the list of clients of a dynamic namespace?"); - } - const rooms = new Set(this.rooms); - this.rooms.clear(); - return this.adapter.sockets(rooms); - } - /** - * Sets the compress flag. - * - * @param {Boolean} compress - if `true`, compresses the sending data - * @return {Namespace} self - */ - compress(compress) { - this.flags.compress = compress; - return this; - } - /** - * Sets the binary flag - * - * @param {Boolean} binary - encode as if it has binary data if `true`, Encode as if it doesnt have binary data if `false` - * @return {Namespace} self - */ - binary(binary) { - this.flags.binary = binary; - return this; - } - /** - * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to - * receive messages (because of network slowness or other issues, or because they’re connected through long polling - * and is in the middle of a request-response cycle). - * - * @return {Namespace} self - */ - get volatile() { - this.flags.volatile = true; - return this; - } - /** - * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node. - * - * @return {Namespace} self - */ - get local() { - this.flags.local = true; - return this; - } -} -exports.Namespace = Namespace; diff --git a/dist/parent-namespace.d.ts b/dist/parent-namespace.d.ts deleted file mode 100644 index 65f817f6bc..0000000000 --- a/dist/parent-namespace.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Namespace } from "./namespace"; -export declare class ParentNamespace extends Namespace { - private static count; - private children; - constructor(server: any); - initAdapter(): void; - emit(...args: any[]): Namespace; - createChild(name: any): Namespace; -} diff --git a/dist/parent-namespace.js b/dist/parent-namespace.js deleted file mode 100644 index 79e22348bb..0000000000 --- a/dist/parent-namespace.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ParentNamespace = void 0; -const namespace_1 = require("./namespace"); -class ParentNamespace extends namespace_1.Namespace { - constructor(server) { - super(server, "/_" + ParentNamespace.count++); - this.children = new Set(); - } - initAdapter() { } - emit(...args) { - this.children.forEach(nsp => { - nsp.rooms = this.rooms; - nsp.flags = this.flags; - nsp.emit.apply(nsp, args); - }); - this.rooms.clear(); - this.flags = {}; - return this; - } - createChild(name) { - const namespace = new namespace_1.Namespace(this.server, name); - namespace.fns = this.fns.slice(0); - this.listeners("connect").forEach(listener => - // @ts-ignore - namespace.on("connect", listener)); - this.listeners("connection").forEach(listener => - // @ts-ignore - namespace.on("connection", listener)); - this.children.add(namespace); - this.server.nsps.set(name, namespace); - return namespace; - } -} -exports.ParentNamespace = ParentNamespace; -ParentNamespace.count = 0; diff --git a/dist/socket.d.ts b/dist/socket.d.ts deleted file mode 100644 index b138833f9f..0000000000 --- a/dist/socket.d.ts +++ /dev/null @@ -1,258 +0,0 @@ -/// -import { EventEmitter } from "events"; -import { Client } from "./client"; -import { Namespace } from "./namespace"; -import { IncomingMessage } from "http"; -import { Room, SocketId } from "socket.io-adapter"; -export declare const RESERVED_EVENTS: Set; -/** - * The handshake details - */ -export interface Handshake { - /** - * The headers sent as part of the handshake - */ - headers: object; - /** - * The date of creation (as string) - */ - time: string; - /** - * The ip of the client - */ - address: string; - /** - * Whether the connection is cross-domain - */ - xdomain: boolean; - /** - * Whether the connection is secure - */ - secure: boolean; - /** - * The date of creation (as unix timestamp) - */ - issued: number; - /** - * The request URL string - */ - url: string; - /** - * The query object - */ - query: object; - /** - * The auth object - */ - auth: object; -} -export declare class Socket extends EventEmitter { - readonly nsp: Namespace; - readonly client: Client; - readonly id: SocketId; - readonly handshake: Handshake; - connected: boolean; - disconnected: boolean; - private readonly server; - private readonly adapter; - private acks; - private fns; - private flags; - private _rooms; - /** - * Interface to a `Client` for a given `Namespace`. - * - * @param {Namespace} nsp - * @param {Client} client - * @param {Object} auth - * @package - */ - constructor(nsp: Namespace, client: Client, auth: object); - /** - * Builds the `handshake` BC object - */ - private buildHandshake; - /** - * Emits to this client. - * - * @return {Socket} self - */ - emit(ev: string, ...args: any[]): this; - /** - * Targets a room when broadcasting. - * - * @param {String} name - * @return {Socket} self - */ - to(name: Room): this; - /** - * Targets a room when broadcasting. - * - * @param {String} name - * @return {Socket} self - */ - in(name: Room): Socket; - /** - * Sends a `message` event. - * - * @return {Socket} self - */ - send(...args: any[]): Socket; - /** - * Sends a `message` event. - * - * @return {Socket} self - */ - write(...args: any[]): Socket; - /** - * Writes a packet. - * - * @param {Object} packet - packet object - * @param {Object} opts - options - */ - private packet; - /** - * Joins a room. - * - * @param {String|Array} rooms - room or array of rooms - * @param {Function} fn - optional, callback - * @return {Socket} self - */ - join(rooms: Room | Array, fn?: (err: Error) => void): Socket; - /** - * Leaves a room. - * - * @param {String} room - * @param {Function} fn - optional, callback - * @return {Socket} self - */ - leave(room: string, fn?: (err: Error) => void): Socket; - /** - * Leave all rooms. - */ - private leaveAll; - /** - * Called by `Namespace` upon successful - * middleware execution (ie: authorization). - * Socket is added to namespace array before - * call to join, so adapters can access it. - * - * @package - */ - onconnect(): void; - /** - * Called with each packet. Called by `Client`. - * - * @param {Object} packet - * @package - */ - onpacket(packet: any): void; - /** - * Called upon event packet. - * - * @param {Object} packet - packet object - */ - private onevent; - /** - * Produces an ack callback to emit with an event. - * - * @param {Number} id - packet id - */ - private ack; - /** - * Called upon ack packet. - */ - private onack; - /** - * Called upon client disconnect packet. - */ - private ondisconnect; - /** - * Handles a client error. - * - * @package - */ - onerror(err: any): void; - /** - * Called upon closing. Called by `Client`. - * - * @param {String} reason - * @throw {Error} optional error object - * - * @package - */ - onclose(reason: string): this; - /** - * Produces an `error` packet. - * - * @param {Object} err - error object - * - * @package - */ - error(err: any): void; - /** - * Disconnects this client. - * - * @param {Boolean} close - if `true`, closes the underlying connection - * @return {Socket} self - */ - disconnect(close?: boolean): Socket; - /** - * Sets the compress flag. - * - * @param {Boolean} compress - if `true`, compresses the sending data - * @return {Socket} self - */ - compress(compress: boolean): Socket; - /** - * Sets the binary flag - * - * @param {Boolean} binary - encode as if it has binary data if `true`, Encode as if it doesnt have binary data if `false` - * @return {Socket} self - */ - binary(binary: boolean): Socket; - /** - * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to - * receive messages (because of network slowness or other issues, or because they’re connected through long polling - * and is in the middle of a request-response cycle). - * - * @return {Socket} self - */ - get volatile(): Socket; - /** - * Sets a modifier for a subsequent event emission that the event data will only be broadcast to every sockets but the - * sender. - * - * @return {Socket} self - */ - get broadcast(): Socket; - /** - * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node. - * - * @return {Socket} self - */ - get local(): Socket; - /** - * Dispatch incoming event to socket listeners. - * - * @param {Array} event - event that will get emitted - */ - private dispatch; - /** - * Sets up socket middleware. - * - * @param {Function} fn - middleware function (event, next) - * @return {Socket} self - */ - use(fn: (event: Array, next: (err: Error) => void) => void): Socket; - /** - * Executes the middleware for an incoming event. - * - * @param {Array} event - event that will get emitted - * @param {Function} fn - last fn call in the middleware - */ - private run; - get request(): IncomingMessage; - get conn(): any; - get rooms(): Set; -} diff --git a/dist/socket.js b/dist/socket.js deleted file mode 100644 index a484cc55d6..0000000000 --- a/dist/socket.js +++ /dev/null @@ -1,467 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Socket = exports.RESERVED_EVENTS = void 0; -const events_1 = require("events"); -const socket_io_parser_1 = require("socket.io-parser"); -const has_binary2_1 = __importDefault(require("has-binary2")); -const url_1 = __importDefault(require("url")); -const debug_1 = __importDefault(require("debug")); -const base64id_1 = __importDefault(require("base64id")); -const debug = debug_1.default("socket.io:socket"); -exports.RESERVED_EVENTS = new Set([ - "error", - "connect", - "disconnect", - "disconnecting", - // EventEmitter reserved events: https://nodejs.org/api/events.html#events_event_newlistener - "newListener", - "removeListener" -]); -class Socket extends events_1.EventEmitter { - /** - * Interface to a `Client` for a given `Namespace`. - * - * @param {Namespace} nsp - * @param {Client} client - * @param {Object} auth - * @package - */ - constructor(nsp, client, auth) { - super(); - this.nsp = nsp; - this.client = client; - this.acks = new Map(); - this.fns = []; - this.flags = {}; - this._rooms = new Set(); - this.server = nsp.server; - this.adapter = this.nsp.adapter; - this.id = base64id_1.default.generateId(); // don't reuse the Engine.IO id because it's sensitive information - this.connected = true; - this.disconnected = false; - this.handshake = this.buildHandshake(auth); - } - /** - * Builds the `handshake` BC object - */ - buildHandshake(auth) { - return { - headers: this.request.headers, - time: new Date() + "", - address: this.conn.remoteAddress, - xdomain: !!this.request.headers.origin, - // @ts-ignore - secure: !!this.request.connection.encrypted, - issued: +new Date(), - url: this.request.url, - query: url_1.default.parse(this.request.url, true).query, - auth - }; - } - /** - * Emits to this client. - * - * @return {Socket} self - */ - // @ts-ignore - emit(ev, ...args) { - if (exports.RESERVED_EVENTS.has(ev)) { - throw new Error(`"${ev}" is a reserved event name`); - } - args.unshift(ev); - const packet = { - type: (this.flags.binary !== undefined - ? this.flags.binary - : has_binary2_1.default(args)) - ? socket_io_parser_1.PacketType.BINARY_EVENT - : socket_io_parser_1.PacketType.EVENT, - data: args - }; - // access last argument to see if it's an ACK callback - if (typeof args[args.length - 1] === "function") { - if (this._rooms.size || this.flags.broadcast) { - throw new Error("Callbacks are not supported when broadcasting"); - } - debug("emitting packet with ack id %d", this.nsp.ids); - this.acks.set(this.nsp.ids, args.pop()); - packet.id = this.nsp.ids++; - } - const rooms = new Set(this._rooms); - const flags = Object.assign({}, this.flags); - // reset flags - this._rooms.clear(); - this.flags = {}; - if (rooms.size || flags.broadcast) { - this.adapter.broadcast(packet, { - except: new Set([this.id]), - rooms: rooms, - flags: flags - }); - } - else { - // dispatch packet - this.packet(packet, flags); - } - return this; - } - /** - * Targets a room when broadcasting. - * - * @param {String} name - * @return {Socket} self - */ - to(name) { - this._rooms.add(name); - return this; - } - /** - * Targets a room when broadcasting. - * - * @param {String} name - * @return {Socket} self - */ - in(name) { - this._rooms.add(name); - return this; - } - /** - * Sends a `message` event. - * - * @return {Socket} self - */ - send(...args) { - args.unshift("message"); - this.emit.apply(this, args); - return this; - } - /** - * Sends a `message` event. - * - * @return {Socket} self - */ - write(...args) { - args.unshift("message"); - this.emit.apply(this, args); - return this; - } - /** - * Writes a packet. - * - * @param {Object} packet - packet object - * @param {Object} opts - options - */ - packet(packet, opts = {}) { - packet.nsp = this.nsp.name; - opts.compress = false !== opts.compress; - this.client.packet(packet, opts); - } - /** - * Joins a room. - * - * @param {String|Array} rooms - room or array of rooms - * @param {Function} fn - optional, callback - * @return {Socket} self - */ - join(rooms, fn) { - debug("joining room %s", rooms); - this.adapter.addAll(this.id, new Set(Array.isArray(rooms) ? rooms : [rooms])); - debug("joined room %s", rooms); - fn && fn(null); - return this; - } - /** - * Leaves a room. - * - * @param {String} room - * @param {Function} fn - optional, callback - * @return {Socket} self - */ - leave(room, fn) { - debug("leave room %s", room); - this.adapter.del(this.id, room); - debug("left room %s", room); - fn && fn(null); - return this; - } - /** - * Leave all rooms. - */ - leaveAll() { - this.adapter.delAll(this.id); - } - /** - * Called by `Namespace` upon successful - * middleware execution (ie: authorization). - * Socket is added to namespace array before - * call to join, so adapters can access it. - * - * @package - */ - onconnect() { - debug("socket connected - writing packet"); - this.nsp.connected.set(this.id, this); - this.join(this.id); - this.packet({ type: socket_io_parser_1.PacketType.CONNECT, data: { sid: this.id } }); - } - /** - * Called with each packet. Called by `Client`. - * - * @param {Object} packet - * @package - */ - onpacket(packet) { - debug("got packet %j", packet); - switch (packet.type) { - case socket_io_parser_1.PacketType.EVENT: - this.onevent(packet); - break; - case socket_io_parser_1.PacketType.BINARY_EVENT: - this.onevent(packet); - break; - case socket_io_parser_1.PacketType.ACK: - this.onack(packet); - break; - case socket_io_parser_1.PacketType.BINARY_ACK: - this.onack(packet); - break; - case socket_io_parser_1.PacketType.DISCONNECT: - this.ondisconnect(); - break; - case socket_io_parser_1.PacketType.ERROR: - this.onerror(new Error(packet.data)); - } - } - /** - * Called upon event packet. - * - * @param {Object} packet - packet object - */ - onevent(packet) { - const args = packet.data || []; - debug("emitting event %j", args); - if (null != packet.id) { - debug("attaching ack callback to event"); - args.push(this.ack(packet.id)); - } - this.dispatch(args); - } - /** - * Produces an ack callback to emit with an event. - * - * @param {Number} id - packet id - */ - ack(id) { - const self = this; - let sent = false; - return function () { - // prevent double callbacks - if (sent) - return; - const args = Array.prototype.slice.call(arguments); - debug("sending ack %j", args); - self.packet({ - id: id, - type: has_binary2_1.default(args) ? socket_io_parser_1.PacketType.BINARY_ACK : socket_io_parser_1.PacketType.ACK, - data: args - }); - sent = true; - }; - } - /** - * Called upon ack packet. - */ - onack(packet) { - const ack = this.acks.get(packet.id); - if ("function" == typeof ack) { - debug("calling ack %s with %j", packet.id, packet.data); - ack.apply(this, packet.data); - this.acks.delete(packet.id); - } - else { - debug("bad ack %s", packet.id); - } - } - /** - * Called upon client disconnect packet. - */ - ondisconnect() { - debug("got disconnect packet"); - this.onclose("client namespace disconnect"); - } - /** - * Handles a client error. - * - * @package - */ - onerror(err) { - if (this.listeners("error").length) { - super.emit("error", err); - } - else { - console.error("Missing error handler on `socket`."); - console.error(err.stack); - } - } - /** - * Called upon closing. Called by `Client`. - * - * @param {String} reason - * @throw {Error} optional error object - * - * @package - */ - onclose(reason) { - if (!this.connected) - return this; - debug("closing socket - reason %s", reason); - super.emit("disconnecting", reason); - this.leaveAll(); - this.nsp.remove(this); - this.client.remove(this); - this.connected = false; - this.disconnected = true; - this.nsp.connected.delete(this.id); - super.emit("disconnect", reason); - } - /** - * Produces an `error` packet. - * - * @param {Object} err - error object - * - * @package - */ - error(err) { - this.packet({ type: socket_io_parser_1.PacketType.ERROR, data: err }); - } - /** - * Disconnects this client. - * - * @param {Boolean} close - if `true`, closes the underlying connection - * @return {Socket} self - */ - disconnect(close = false) { - if (!this.connected) - return this; - if (close) { - this.client.disconnect(); - } - else { - this.packet({ type: socket_io_parser_1.PacketType.DISCONNECT }); - this.onclose("server namespace disconnect"); - } - return this; - } - /** - * Sets the compress flag. - * - * @param {Boolean} compress - if `true`, compresses the sending data - * @return {Socket} self - */ - compress(compress) { - this.flags.compress = compress; - return this; - } - /** - * Sets the binary flag - * - * @param {Boolean} binary - encode as if it has binary data if `true`, Encode as if it doesnt have binary data if `false` - * @return {Socket} self - */ - binary(binary) { - this.flags.binary = binary; - return this; - } - /** - * Sets a modifier for a subsequent event emission that the event data may be lost if the client is not ready to - * receive messages (because of network slowness or other issues, or because they’re connected through long polling - * and is in the middle of a request-response cycle). - * - * @return {Socket} self - */ - get volatile() { - this.flags.volatile = true; - return this; - } - /** - * Sets a modifier for a subsequent event emission that the event data will only be broadcast to every sockets but the - * sender. - * - * @return {Socket} self - */ - get broadcast() { - this.flags.broadcast = true; - return this; - } - /** - * Sets a modifier for a subsequent event emission that the event data will only be broadcast to the current node. - * - * @return {Socket} self - */ - get local() { - this.flags.local = true; - return this; - } - /** - * Dispatch incoming event to socket listeners. - * - * @param {Array} event - event that will get emitted - */ - dispatch(event) { - debug("dispatching an event %j", event); - this.run(event, err => { - process.nextTick(() => { - if (err) { - return this.error(err.message); - } - super.emit.apply(this, event); - }); - }); - } - /** - * Sets up socket middleware. - * - * @param {Function} fn - middleware function (event, next) - * @return {Socket} self - */ - use(fn) { - this.fns.push(fn); - return this; - } - /** - * Executes the middleware for an incoming event. - * - * @param {Array} event - event that will get emitted - * @param {Function} fn - last fn call in the middleware - */ - run(event, fn) { - const fns = this.fns.slice(0); - if (!fns.length) - return fn(null); - function run(i) { - fns[i](event, function (err) { - // upon error, short-circuit - if (err) - return fn(err); - // if no middleware left, summon callback - if (!fns[i + 1]) - return fn(null); - // go on to next - run(i + 1); - }); - } - run(0); - } - get request() { - return this.client.request; - } - get conn() { - return this.client.conn; - } - get rooms() { - return this.adapter.socketRooms(this.id) || new Set(); - } -} -exports.Socket = Socket; diff --git a/package.json b/package.json index 957d432886..d937a6891e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "socket.io", - "version": "2.3.0", + "version": "3.0.0-rc1", "description": "node.js realtime framework server", "keywords": [ "realtime", @@ -29,7 +29,8 @@ "scripts": { "test": "npm run format:check && tsc && nyc mocha --require ts-node/register --reporter spec --slow 200 --bail --timeout 10000 test/socket.io.ts", "format:check": "prettier --check 'lib/**/*.ts' 'test/**/*.ts'", - "format:fix": "prettier --write 'lib/**/*.ts' 'test/**/*.ts'" + "format:fix": "prettier --write 'lib/**/*.ts' 'test/**/*.ts'", + "prepack": "tsc" }, "dependencies": { "base64id": "~2.0.0", @@ -37,8 +38,8 @@ "engine.io": "~4.0.0", "has-binary2": "~1.0.2", "socket.io-adapter": "~2.0.1", - "socket.io-client": "github:socketio/socket.io-client#develop", - "socket.io-parser": "github:socketio/socket.io-parser#develop" + "socket.io-client": "3.0.0-rc1", + "socket.io-parser": "4.0.1-rc1" }, "devDependencies": { "@types/cookie": "^0.4.0",