Chat erstellen
This commit is contained in:
parent
fe47867974
commit
4ae2de8343
56
app.js
56
app.js
@ -4,6 +4,8 @@ const express = require("express");
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const helmet = require("helmet");
|
const helmet = require("helmet");
|
||||||
const rateLimit = require("express-rate-limit");
|
const rateLimit = require("express-rate-limit");
|
||||||
|
const http = require("http");
|
||||||
|
const { Server } = require("socket.io");
|
||||||
|
|
||||||
const serverRoutes = require("./routes/servers");
|
const serverRoutes = require("./routes/servers");
|
||||||
const registerRoutes = require("./routes/register");
|
const registerRoutes = require("./routes/register");
|
||||||
@ -17,6 +19,13 @@ const buildingRoutes = require("./routes/buildings");
|
|||||||
const app = express();
|
const app = express();
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
|
|
||||||
|
/* ========================
|
||||||
|
Chatserver
|
||||||
|
======================== */
|
||||||
|
|
||||||
|
const server = http.createServer(app);
|
||||||
|
const io = new Server(server);
|
||||||
|
|
||||||
/* ========================
|
/* ========================
|
||||||
Security Middleware
|
Security Middleware
|
||||||
======================== */
|
======================== */
|
||||||
@ -104,10 +113,55 @@ app.use((req, res) => {
|
|||||||
const compression = require("compression");
|
const compression = require("compression");
|
||||||
app.use(compression());
|
app.use(compression());
|
||||||
|
|
||||||
|
/* ========================
|
||||||
|
Chat System
|
||||||
|
======================== */
|
||||||
|
|
||||||
|
let onlineUsers = {};
|
||||||
|
|
||||||
|
io.on("connection", (socket) => {
|
||||||
|
console.log("Spieler verbunden");
|
||||||
|
|
||||||
|
socket.on("register", (username) => {
|
||||||
|
socket.user = username;
|
||||||
|
onlineUsers[username] = socket.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("chatMessage", (data) => {
|
||||||
|
if (data.channel === "global") {
|
||||||
|
io.emit("chatMessage", {
|
||||||
|
user: socket.user,
|
||||||
|
message: data.message,
|
||||||
|
channel: "global",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.channel === "guild") {
|
||||||
|
io.to("guild_" + data.guild).emit("chatMessage", {
|
||||||
|
user: socket.user,
|
||||||
|
message: data.message,
|
||||||
|
channel: "guild",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("privateMessage", (data) => {
|
||||||
|
const target = onlineUsers[data.to];
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
io.to(target).emit("chatMessage", {
|
||||||
|
user: socket.user,
|
||||||
|
message: data.message,
|
||||||
|
channel: "private",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
/* ========================
|
/* ========================
|
||||||
Server Start
|
Server Start
|
||||||
======================== */
|
======================== */
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
server.listen(PORT, () => {
|
||||||
console.log(`Dynasty of Knights Server läuft auf http://localhost:${PORT}`);
|
console.log(`Dynasty of Knights Server läuft auf http://localhost:${PORT}`);
|
||||||
});
|
});
|
||||||
|
|||||||
241
node_modules/.package-lock.json
generated
vendored
241
node_modules/.package-lock.json
generated
vendored
@ -37,6 +37,12 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@socket.io/component-emitter": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@tootallnate/once": {
|
"node_modules/@tootallnate/once": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
||||||
@ -47,16 +53,33 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/cors": {
|
||||||
|
"version": "2.8.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
|
||||||
|
"integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "25.4.0",
|
"version": "25.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.4.0.tgz",
|
||||||
"integrity": "sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==",
|
"integrity": "sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~7.18.0"
|
"undici-types": "~7.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ws": {
|
||||||
|
"version": "8.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||||
|
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/abbrev": {
|
"node_modules/abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
@ -185,6 +208,15 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/base64id": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^4.5.0 || >= 5.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bcrypt": {
|
"node_modules/bcrypt": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
|
||||||
@ -506,6 +538,23 @@
|
|||||||
"node": ">=6.6.0"
|
"node": ">=6.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cors": {
|
||||||
|
"version": "2.8.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
|
||||||
|
"integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"object-assign": "^4",
|
||||||
|
"vary": "^1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/crypto": {
|
"node_modules/crypto": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
|
||||||
@ -774,6 +823,79 @@
|
|||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/engine.io": {
|
||||||
|
"version": "6.6.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.6.tgz",
|
||||||
|
"integrity": "sha512-U2SN0w3OpjFRVlrc17E6TMDmH58Xl9rai1MblNjAdwWp07Kk+llmzX0hjDpQdrDGzwmvOtgM5yI+meYX6iZ2xA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/cors": "^2.8.12",
|
||||||
|
"@types/node": ">=10.0.0",
|
||||||
|
"@types/ws": "^8.5.12",
|
||||||
|
"accepts": "~1.3.4",
|
||||||
|
"base64id": "2.0.0",
|
||||||
|
"cookie": "~0.7.2",
|
||||||
|
"cors": "~2.8.5",
|
||||||
|
"debug": "~4.4.1",
|
||||||
|
"engine.io-parser": "~5.2.1",
|
||||||
|
"ws": "~8.18.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io-parser": {
|
||||||
|
"version": "5.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
|
||||||
|
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io/node_modules/accepts": {
|
||||||
|
"version": "1.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
|
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-types": "~2.1.34",
|
||||||
|
"negotiator": "0.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io/node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io/node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io/node_modules/negotiator": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/env-paths": {
|
"node_modules/env-paths": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||||
@ -1815,6 +1937,15 @@
|
|||||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/object-assign": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-inspect": {
|
"node_modules/object-inspect": {
|
||||||
"version": "1.13.4",
|
"version": "1.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||||
@ -2330,6 +2461,90 @@
|
|||||||
"npm": ">= 3.0.0"
|
"npm": ">= 3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/socket.io": {
|
||||||
|
"version": "4.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz",
|
||||||
|
"integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"accepts": "~1.3.4",
|
||||||
|
"base64id": "~2.0.0",
|
||||||
|
"cors": "~2.8.5",
|
||||||
|
"debug": "~4.4.1",
|
||||||
|
"engine.io": "~6.6.0",
|
||||||
|
"socket.io-adapter": "~2.5.2",
|
||||||
|
"socket.io-parser": "~4.2.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socket.io-adapter": {
|
||||||
|
"version": "2.5.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz",
|
||||||
|
"integrity": "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "~4.4.1",
|
||||||
|
"ws": "~8.18.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socket.io-parser": {
|
||||||
|
"version": "4.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz",
|
||||||
|
"integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.4.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socket.io/node_modules/accepts": {
|
||||||
|
"version": "1.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
|
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-types": "~2.1.34",
|
||||||
|
"negotiator": "0.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socket.io/node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socket.io/node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socket.io/node_modules/negotiator": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/socks": {
|
"node_modules/socks": {
|
||||||
"version": "2.8.7",
|
"version": "2.8.7",
|
||||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
|
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
|
||||||
@ -2588,8 +2803,7 @@
|
|||||||
"version": "7.18.2",
|
"version": "7.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||||
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/unique-filename": {
|
"node_modules/unique-filename": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@ -2667,6 +2881,27 @@
|
|||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||||
|
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yallist": {
|
"node_modules/yallist": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
|||||||
24
node_modules/@socket.io/component-emitter/LICENSE
generated
vendored
Normal file
24
node_modules/@socket.io/component-emitter/LICENSE
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Component contributors <dev@component.io>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
79
node_modules/@socket.io/component-emitter/Readme.md
generated
vendored
Normal file
79
node_modules/@socket.io/component-emitter/Readme.md
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# `@socket.io/component-emitter`
|
||||||
|
|
||||||
|
Event emitter component.
|
||||||
|
|
||||||
|
This project is a fork of the [`component-emitter`](https://github.com/sindresorhus/component-emitter) project, with [Socket.IO](https://socket.io/)-specific TypeScript typings.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm i @socket.io/component-emitter
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Emitter(obj)
|
||||||
|
|
||||||
|
The `Emitter` may also be used as a mixin. For example
|
||||||
|
a "plain" object may become an emitter, or you may
|
||||||
|
extend an existing prototype.
|
||||||
|
|
||||||
|
As an `Emitter` instance:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Emitter } from '@socket.io/component-emitter';
|
||||||
|
|
||||||
|
var emitter = new Emitter;
|
||||||
|
emitter.emit('something');
|
||||||
|
```
|
||||||
|
|
||||||
|
As a mixin:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Emitter } from '@socket.io/component-emitter';
|
||||||
|
|
||||||
|
var user = { name: 'tobi' };
|
||||||
|
Emitter(user);
|
||||||
|
|
||||||
|
user.emit('im a user');
|
||||||
|
```
|
||||||
|
|
||||||
|
As a prototype mixin:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Emitter } from '@socket.io/component-emitter';
|
||||||
|
|
||||||
|
Emitter(User.prototype);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Emitter#on(event, fn)
|
||||||
|
|
||||||
|
Register an `event` handler `fn`.
|
||||||
|
|
||||||
|
### Emitter#once(event, fn)
|
||||||
|
|
||||||
|
Register a single-shot `event` handler `fn`,
|
||||||
|
removed immediately after it is invoked the
|
||||||
|
first time.
|
||||||
|
|
||||||
|
### Emitter#off(event, fn)
|
||||||
|
|
||||||
|
* Pass `event` and `fn` to remove a listener.
|
||||||
|
* Pass `event` to remove all listeners on that event.
|
||||||
|
* Pass nothing to remove all listeners on all events.
|
||||||
|
|
||||||
|
### Emitter#emit(event, ...)
|
||||||
|
|
||||||
|
Emit an `event` with variable option args.
|
||||||
|
|
||||||
|
### Emitter#listeners(event)
|
||||||
|
|
||||||
|
Return an array of callbacks, or an empty array.
|
||||||
|
|
||||||
|
### Emitter#hasListeners(event)
|
||||||
|
|
||||||
|
Check if this emitter has `event` handlers.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
179
node_modules/@socket.io/component-emitter/lib/cjs/index.d.ts
generated
vendored
Normal file
179
node_modules/@socket.io/component-emitter/lib/cjs/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/**
|
||||||
|
* An events map is an interface that maps event names to their value, which
|
||||||
|
* represents the type of the `on` listener.
|
||||||
|
*/
|
||||||
|
export interface EventsMap {
|
||||||
|
[event: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default events map, used if no EventsMap is given. Using this EventsMap
|
||||||
|
* is equivalent to accepting all event names, and any data.
|
||||||
|
*/
|
||||||
|
export interface DefaultEventsMap {
|
||||||
|
[event: string]: (...args: any[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a union type containing all the keys of an event map.
|
||||||
|
*/
|
||||||
|
export type EventNames<Map extends EventsMap> = keyof Map & (string | symbol);
|
||||||
|
|
||||||
|
/** The tuple type representing the parameters of an event listener */
|
||||||
|
export type EventParams<
|
||||||
|
Map extends EventsMap,
|
||||||
|
Ev extends EventNames<Map>
|
||||||
|
> = Parameters<Map[Ev]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The event names that are either in ReservedEvents or in UserEvents
|
||||||
|
*/
|
||||||
|
export type ReservedOrUserEventNames<
|
||||||
|
ReservedEventsMap extends EventsMap,
|
||||||
|
UserEvents extends EventsMap
|
||||||
|
> = EventNames<ReservedEventsMap> | EventNames<UserEvents>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of a listener of a user event or a reserved event. If `Ev` is in
|
||||||
|
* `ReservedEvents`, the reserved event listener is returned.
|
||||||
|
*/
|
||||||
|
export type ReservedOrUserListener<
|
||||||
|
ReservedEvents extends EventsMap,
|
||||||
|
UserEvents extends EventsMap,
|
||||||
|
Ev extends ReservedOrUserEventNames<ReservedEvents, UserEvents>
|
||||||
|
> = FallbackToUntypedListener<
|
||||||
|
Ev extends EventNames<ReservedEvents>
|
||||||
|
? ReservedEvents[Ev]
|
||||||
|
: Ev extends EventNames<UserEvents>
|
||||||
|
? UserEvents[Ev]
|
||||||
|
: never
|
||||||
|
>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an untyped listener type if `T` is `never`; otherwise, returns `T`.
|
||||||
|
*
|
||||||
|
* This is a hack to mitigate https://github.com/socketio/socket.io/issues/3833.
|
||||||
|
* Needed because of https://github.com/microsoft/TypeScript/issues/41778
|
||||||
|
*/
|
||||||
|
type FallbackToUntypedListener<T> = [T] extends [never]
|
||||||
|
? (...args: any[]) => void | Promise<void>
|
||||||
|
: T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strictly typed version of an `EventEmitter`. A `TypedEventEmitter` takes type
|
||||||
|
* parameters for mappings of event names to event data types, and strictly
|
||||||
|
* types method calls to the `EventEmitter` according to these event maps.
|
||||||
|
*
|
||||||
|
* @typeParam ListenEvents - `EventsMap` of user-defined events that can be
|
||||||
|
* listened to with `on` or `once`
|
||||||
|
* @typeParam EmitEvents - `EventsMap` of user-defined events that can be
|
||||||
|
* emitted with `emit`
|
||||||
|
* @typeParam ReservedEvents - `EventsMap` of reserved events, that can be
|
||||||
|
* emitted by socket.io with `emitReserved`, and can be listened to with
|
||||||
|
* `listen`.
|
||||||
|
*/
|
||||||
|
export class Emitter<
|
||||||
|
ListenEvents extends EventsMap,
|
||||||
|
EmitEvents extends EventsMap,
|
||||||
|
ReservedEvents extends EventsMap = {}
|
||||||
|
> {
|
||||||
|
/**
|
||||||
|
* Adds the `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param listener Callback function
|
||||||
|
*/
|
||||||
|
on<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
|
||||||
|
ev: Ev,
|
||||||
|
listener: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a one-time `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param listener Callback function
|
||||||
|
*/
|
||||||
|
once<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
|
||||||
|
ev: Ev,
|
||||||
|
listener: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param listener Callback function
|
||||||
|
*/
|
||||||
|
off<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
|
||||||
|
ev?: Ev,
|
||||||
|
listener?: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits an event.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param args Values to send to listeners of this event
|
||||||
|
*/
|
||||||
|
emit<Ev extends EventNames<EmitEvents>>(
|
||||||
|
ev: Ev,
|
||||||
|
...args: EventParams<EmitEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits a reserved event.
|
||||||
|
*
|
||||||
|
* This method is `protected`, so that only a class extending
|
||||||
|
* `StrictEventEmitter` can emit its own reserved events.
|
||||||
|
*
|
||||||
|
* @param ev Reserved event name
|
||||||
|
* @param args Arguments to emit along with the event
|
||||||
|
*/
|
||||||
|
protected emitReserved<Ev extends EventNames<ReservedEvents>>(
|
||||||
|
ev: Ev,
|
||||||
|
...args: EventParams<ReservedEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the listeners listening to an event.
|
||||||
|
*
|
||||||
|
* @param event Event name
|
||||||
|
* @returns Array of listeners subscribed to `event`
|
||||||
|
*/
|
||||||
|
listeners<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
|
||||||
|
event: Ev
|
||||||
|
): ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there is a listener for this event.
|
||||||
|
*
|
||||||
|
* @param event Event name
|
||||||
|
* @returns boolean
|
||||||
|
*/
|
||||||
|
hasListeners<
|
||||||
|
Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>
|
||||||
|
>(event: Ev): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param listener Callback function
|
||||||
|
*/
|
||||||
|
removeListener<
|
||||||
|
Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>
|
||||||
|
>(
|
||||||
|
ev?: Ev,
|
||||||
|
listener?: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
*/
|
||||||
|
removeAllListeners<
|
||||||
|
Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>
|
||||||
|
>(ev?: Ev): this;
|
||||||
|
}
|
||||||
176
node_modules/@socket.io/component-emitter/lib/cjs/index.js
generated
vendored
Normal file
176
node_modules/@socket.io/component-emitter/lib/cjs/index.js
generated
vendored
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Expose `Emitter`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.Emitter = Emitter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a new `Emitter`.
|
||||||
|
*
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Emitter(obj) {
|
||||||
|
if (obj) return mixin(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin the emitter properties.
|
||||||
|
*
|
||||||
|
* @param {Object} obj
|
||||||
|
* @return {Object}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function mixin(obj) {
|
||||||
|
for (var key in Emitter.prototype) {
|
||||||
|
obj[key] = Emitter.prototype[key];
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen on the given `event` with `fn`.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @param {Function} fn
|
||||||
|
* @return {Emitter}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.on =
|
||||||
|
Emitter.prototype.addEventListener = function(event, fn){
|
||||||
|
this._callbacks = this._callbacks || {};
|
||||||
|
(this._callbacks['$' + event] = this._callbacks['$' + event] || [])
|
||||||
|
.push(fn);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an `event` listener that will be invoked a single
|
||||||
|
* time then automatically removed.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @param {Function} fn
|
||||||
|
* @return {Emitter}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.once = function(event, fn){
|
||||||
|
function on() {
|
||||||
|
this.off(event, on);
|
||||||
|
fn.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
on.fn = fn;
|
||||||
|
this.on(event, on);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the given callback for `event` or all
|
||||||
|
* registered callbacks.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @param {Function} fn
|
||||||
|
* @return {Emitter}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.off =
|
||||||
|
Emitter.prototype.removeListener =
|
||||||
|
Emitter.prototype.removeAllListeners =
|
||||||
|
Emitter.prototype.removeEventListener = function(event, fn){
|
||||||
|
this._callbacks = this._callbacks || {};
|
||||||
|
|
||||||
|
// all
|
||||||
|
if (0 == arguments.length) {
|
||||||
|
this._callbacks = {};
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// specific event
|
||||||
|
var callbacks = this._callbacks['$' + event];
|
||||||
|
if (!callbacks) return this;
|
||||||
|
|
||||||
|
// remove all handlers
|
||||||
|
if (1 == arguments.length) {
|
||||||
|
delete this._callbacks['$' + event];
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove specific handler
|
||||||
|
var cb;
|
||||||
|
for (var i = 0; i < callbacks.length; i++) {
|
||||||
|
cb = callbacks[i];
|
||||||
|
if (cb === fn || cb.fn === fn) {
|
||||||
|
callbacks.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove event specific arrays for event types that no
|
||||||
|
// one is subscribed for to avoid memory leak.
|
||||||
|
if (callbacks.length === 0) {
|
||||||
|
delete this._callbacks['$' + event];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emit `event` with the given args.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @param {Mixed} ...
|
||||||
|
* @return {Emitter}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.emit = function(event){
|
||||||
|
this._callbacks = this._callbacks || {};
|
||||||
|
|
||||||
|
var args = new Array(arguments.length - 1)
|
||||||
|
, callbacks = this._callbacks['$' + event];
|
||||||
|
|
||||||
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
|
args[i - 1] = arguments[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks) {
|
||||||
|
callbacks = callbacks.slice(0);
|
||||||
|
for (var i = 0, len = callbacks.length; i < len; ++i) {
|
||||||
|
callbacks[i].apply(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// alias used for reserved events (protected method)
|
||||||
|
Emitter.prototype.emitReserved = Emitter.prototype.emit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return array of callbacks for `event`.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @return {Array}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.listeners = function(event){
|
||||||
|
this._callbacks = this._callbacks || {};
|
||||||
|
return this._callbacks['$' + event] || [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this emitter has `event` handlers.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @return {Boolean}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.hasListeners = function(event){
|
||||||
|
return !! this.listeners(event).length;
|
||||||
|
};
|
||||||
4
node_modules/@socket.io/component-emitter/lib/cjs/package.json
generated
vendored
Normal file
4
node_modules/@socket.io/component-emitter/lib/cjs/package.json
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"name": "@socket.io/component-emitter",
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
||||||
179
node_modules/@socket.io/component-emitter/lib/esm/index.d.ts
generated
vendored
Normal file
179
node_modules/@socket.io/component-emitter/lib/esm/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/**
|
||||||
|
* An events map is an interface that maps event names to their value, which
|
||||||
|
* represents the type of the `on` listener.
|
||||||
|
*/
|
||||||
|
export interface EventsMap {
|
||||||
|
[event: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default events map, used if no EventsMap is given. Using this EventsMap
|
||||||
|
* is equivalent to accepting all event names, and any data.
|
||||||
|
*/
|
||||||
|
export interface DefaultEventsMap {
|
||||||
|
[event: string]: (...args: any[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a union type containing all the keys of an event map.
|
||||||
|
*/
|
||||||
|
export type EventNames<Map extends EventsMap> = keyof Map & (string | symbol);
|
||||||
|
|
||||||
|
/** The tuple type representing the parameters of an event listener */
|
||||||
|
export type EventParams<
|
||||||
|
Map extends EventsMap,
|
||||||
|
Ev extends EventNames<Map>
|
||||||
|
> = Parameters<Map[Ev]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The event names that are either in ReservedEvents or in UserEvents
|
||||||
|
*/
|
||||||
|
export type ReservedOrUserEventNames<
|
||||||
|
ReservedEventsMap extends EventsMap,
|
||||||
|
UserEvents extends EventsMap
|
||||||
|
> = EventNames<ReservedEventsMap> | EventNames<UserEvents>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of a listener of a user event or a reserved event. If `Ev` is in
|
||||||
|
* `ReservedEvents`, the reserved event listener is returned.
|
||||||
|
*/
|
||||||
|
export type ReservedOrUserListener<
|
||||||
|
ReservedEvents extends EventsMap,
|
||||||
|
UserEvents extends EventsMap,
|
||||||
|
Ev extends ReservedOrUserEventNames<ReservedEvents, UserEvents>
|
||||||
|
> = FallbackToUntypedListener<
|
||||||
|
Ev extends EventNames<ReservedEvents>
|
||||||
|
? ReservedEvents[Ev]
|
||||||
|
: Ev extends EventNames<UserEvents>
|
||||||
|
? UserEvents[Ev]
|
||||||
|
: never
|
||||||
|
>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an untyped listener type if `T` is `never`; otherwise, returns `T`.
|
||||||
|
*
|
||||||
|
* This is a hack to mitigate https://github.com/socketio/socket.io/issues/3833.
|
||||||
|
* Needed because of https://github.com/microsoft/TypeScript/issues/41778
|
||||||
|
*/
|
||||||
|
type FallbackToUntypedListener<T> = [T] extends [never]
|
||||||
|
? (...args: any[]) => void | Promise<void>
|
||||||
|
: T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strictly typed version of an `EventEmitter`. A `TypedEventEmitter` takes type
|
||||||
|
* parameters for mappings of event names to event data types, and strictly
|
||||||
|
* types method calls to the `EventEmitter` according to these event maps.
|
||||||
|
*
|
||||||
|
* @typeParam ListenEvents - `EventsMap` of user-defined events that can be
|
||||||
|
* listened to with `on` or `once`
|
||||||
|
* @typeParam EmitEvents - `EventsMap` of user-defined events that can be
|
||||||
|
* emitted with `emit`
|
||||||
|
* @typeParam ReservedEvents - `EventsMap` of reserved events, that can be
|
||||||
|
* emitted by socket.io with `emitReserved`, and can be listened to with
|
||||||
|
* `listen`.
|
||||||
|
*/
|
||||||
|
export class Emitter<
|
||||||
|
ListenEvents extends EventsMap,
|
||||||
|
EmitEvents extends EventsMap,
|
||||||
|
ReservedEvents extends EventsMap = {}
|
||||||
|
> {
|
||||||
|
/**
|
||||||
|
* Adds the `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param listener Callback function
|
||||||
|
*/
|
||||||
|
on<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
|
||||||
|
ev: Ev,
|
||||||
|
listener: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a one-time `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param listener Callback function
|
||||||
|
*/
|
||||||
|
once<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
|
||||||
|
ev: Ev,
|
||||||
|
listener: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param listener Callback function
|
||||||
|
*/
|
||||||
|
off<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
|
||||||
|
ev?: Ev,
|
||||||
|
listener?: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits an event.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param args Values to send to listeners of this event
|
||||||
|
*/
|
||||||
|
emit<Ev extends EventNames<EmitEvents>>(
|
||||||
|
ev: Ev,
|
||||||
|
...args: EventParams<EmitEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits a reserved event.
|
||||||
|
*
|
||||||
|
* This method is `protected`, so that only a class extending
|
||||||
|
* `StrictEventEmitter` can emit its own reserved events.
|
||||||
|
*
|
||||||
|
* @param ev Reserved event name
|
||||||
|
* @param args Arguments to emit along with the event
|
||||||
|
*/
|
||||||
|
protected emitReserved<Ev extends EventNames<ReservedEvents>>(
|
||||||
|
ev: Ev,
|
||||||
|
...args: EventParams<ReservedEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the listeners listening to an event.
|
||||||
|
*
|
||||||
|
* @param event Event name
|
||||||
|
* @returns Array of listeners subscribed to `event`
|
||||||
|
*/
|
||||||
|
listeners<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
|
||||||
|
event: Ev
|
||||||
|
): ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there is a listener for this event.
|
||||||
|
*
|
||||||
|
* @param event Event name
|
||||||
|
* @returns boolean
|
||||||
|
*/
|
||||||
|
hasListeners<
|
||||||
|
Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>
|
||||||
|
>(event: Ev): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
* @param listener Callback function
|
||||||
|
*/
|
||||||
|
removeListener<
|
||||||
|
Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>
|
||||||
|
>(
|
||||||
|
ev?: Ev,
|
||||||
|
listener?: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all `listener` function as an event listener for `ev`.
|
||||||
|
*
|
||||||
|
* @param ev Name of the event
|
||||||
|
*/
|
||||||
|
removeAllListeners<
|
||||||
|
Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>
|
||||||
|
>(ev?: Ev): this;
|
||||||
|
}
|
||||||
169
node_modules/@socket.io/component-emitter/lib/esm/index.js
generated
vendored
Normal file
169
node_modules/@socket.io/component-emitter/lib/esm/index.js
generated
vendored
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/**
|
||||||
|
* Initialize a new `Emitter`.
|
||||||
|
*
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function Emitter(obj) {
|
||||||
|
if (obj) return mixin(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin the emitter properties.
|
||||||
|
*
|
||||||
|
* @param {Object} obj
|
||||||
|
* @return {Object}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function mixin(obj) {
|
||||||
|
for (var key in Emitter.prototype) {
|
||||||
|
obj[key] = Emitter.prototype[key];
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen on the given `event` with `fn`.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @param {Function} fn
|
||||||
|
* @return {Emitter}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.on =
|
||||||
|
Emitter.prototype.addEventListener = function(event, fn){
|
||||||
|
this._callbacks = this._callbacks || {};
|
||||||
|
(this._callbacks['$' + event] = this._callbacks['$' + event] || [])
|
||||||
|
.push(fn);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an `event` listener that will be invoked a single
|
||||||
|
* time then automatically removed.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @param {Function} fn
|
||||||
|
* @return {Emitter}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.once = function(event, fn){
|
||||||
|
function on() {
|
||||||
|
this.off(event, on);
|
||||||
|
fn.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
on.fn = fn;
|
||||||
|
this.on(event, on);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the given callback for `event` or all
|
||||||
|
* registered callbacks.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @param {Function} fn
|
||||||
|
* @return {Emitter}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.off =
|
||||||
|
Emitter.prototype.removeListener =
|
||||||
|
Emitter.prototype.removeAllListeners =
|
||||||
|
Emitter.prototype.removeEventListener = function(event, fn){
|
||||||
|
this._callbacks = this._callbacks || {};
|
||||||
|
|
||||||
|
// all
|
||||||
|
if (0 == arguments.length) {
|
||||||
|
this._callbacks = {};
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// specific event
|
||||||
|
var callbacks = this._callbacks['$' + event];
|
||||||
|
if (!callbacks) return this;
|
||||||
|
|
||||||
|
// remove all handlers
|
||||||
|
if (1 == arguments.length) {
|
||||||
|
delete this._callbacks['$' + event];
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove specific handler
|
||||||
|
var cb;
|
||||||
|
for (var i = 0; i < callbacks.length; i++) {
|
||||||
|
cb = callbacks[i];
|
||||||
|
if (cb === fn || cb.fn === fn) {
|
||||||
|
callbacks.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove event specific arrays for event types that no
|
||||||
|
// one is subscribed for to avoid memory leak.
|
||||||
|
if (callbacks.length === 0) {
|
||||||
|
delete this._callbacks['$' + event];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emit `event` with the given args.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @param {Mixed} ...
|
||||||
|
* @return {Emitter}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.emit = function(event){
|
||||||
|
this._callbacks = this._callbacks || {};
|
||||||
|
|
||||||
|
var args = new Array(arguments.length - 1)
|
||||||
|
, callbacks = this._callbacks['$' + event];
|
||||||
|
|
||||||
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
|
args[i - 1] = arguments[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks) {
|
||||||
|
callbacks = callbacks.slice(0);
|
||||||
|
for (var i = 0, len = callbacks.length; i < len; ++i) {
|
||||||
|
callbacks[i].apply(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// alias used for reserved events (protected method)
|
||||||
|
Emitter.prototype.emitReserved = Emitter.prototype.emit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return array of callbacks for `event`.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @return {Array}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.listeners = function(event){
|
||||||
|
this._callbacks = this._callbacks || {};
|
||||||
|
return this._callbacks['$' + event] || [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this emitter has `event` handlers.
|
||||||
|
*
|
||||||
|
* @param {String} event
|
||||||
|
* @return {Boolean}
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Emitter.prototype.hasListeners = function(event){
|
||||||
|
return !! this.listeners(event).length;
|
||||||
|
};
|
||||||
4
node_modules/@socket.io/component-emitter/lib/esm/package.json
generated
vendored
Normal file
4
node_modules/@socket.io/component-emitter/lib/esm/package.json
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"name": "@socket.io/component-emitter",
|
||||||
|
"type": "module"
|
||||||
|
}
|
||||||
28
node_modules/@socket.io/component-emitter/package.json
generated
vendored
Normal file
28
node_modules/@socket.io/component-emitter/package.json
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "@socket.io/component-emitter",
|
||||||
|
"description": "Event emitter",
|
||||||
|
"version": "3.1.2",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"mocha": "*",
|
||||||
|
"should": "*"
|
||||||
|
},
|
||||||
|
"component": {
|
||||||
|
"scripts": {
|
||||||
|
"emitter/index.js": "index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"main": "./lib/cjs/index.js",
|
||||||
|
"module": "./lib/esm/index.js",
|
||||||
|
"types": "./lib/cjs/index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/socketio/emitter.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "make test"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib/"
|
||||||
|
]
|
||||||
|
}
|
||||||
21
node_modules/@types/cors/LICENSE
generated
vendored
Normal file
21
node_modules/@types/cors/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
75
node_modules/@types/cors/README.md
generated
vendored
Normal file
75
node_modules/@types/cors/README.md
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/cors`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for cors (https://github.com/expressjs/cors/).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/cors.
|
||||||
|
## [index.d.ts](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/cors/index.d.ts)
|
||||||
|
````ts
|
||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import { IncomingHttpHeaders } from "http";
|
||||||
|
|
||||||
|
type StaticOrigin = boolean | string | RegExp | Array<boolean | string | RegExp>;
|
||||||
|
|
||||||
|
type CustomOrigin = (
|
||||||
|
requestOrigin: string | undefined,
|
||||||
|
callback: (err: Error | null, origin?: StaticOrigin) => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
declare namespace e {
|
||||||
|
interface CorsRequest {
|
||||||
|
method?: string | undefined;
|
||||||
|
headers: IncomingHttpHeaders;
|
||||||
|
}
|
||||||
|
interface CorsOptions {
|
||||||
|
/**
|
||||||
|
* @default '*'
|
||||||
|
*/
|
||||||
|
origin?: StaticOrigin | CustomOrigin | undefined;
|
||||||
|
/**
|
||||||
|
* @default 'GET,HEAD,PUT,PATCH,POST,DELETE'
|
||||||
|
*/
|
||||||
|
methods?: string | string[] | undefined;
|
||||||
|
allowedHeaders?: string | string[] | undefined;
|
||||||
|
exposedHeaders?: string | string[] | undefined;
|
||||||
|
credentials?: boolean | undefined;
|
||||||
|
maxAge?: number | undefined;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
preflightContinue?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* @default 204
|
||||||
|
*/
|
||||||
|
optionsSuccessStatus?: number | undefined;
|
||||||
|
}
|
||||||
|
type CorsOptionsDelegate<T extends CorsRequest = CorsRequest> = (
|
||||||
|
req: T,
|
||||||
|
callback: (err: Error | null, options?: CorsOptions) => void,
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare function e<T extends e.CorsRequest = e.CorsRequest>(
|
||||||
|
options?: e.CorsOptions | e.CorsOptionsDelegate<T>,
|
||||||
|
): (
|
||||||
|
req: T,
|
||||||
|
res: {
|
||||||
|
statusCode?: number | undefined;
|
||||||
|
setHeader(key: string, value: string): any;
|
||||||
|
end(): any;
|
||||||
|
},
|
||||||
|
next: (err?: any) => any,
|
||||||
|
) => void;
|
||||||
|
export = e;
|
||||||
|
|
||||||
|
````
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Sat, 07 Jun 2025 02:15:25 GMT
|
||||||
|
* Dependencies: [@types/node](https://npmjs.com/package/@types/node)
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Alan Plum](https://github.com/pluma), [Gaurav Sharma](https://github.com/gtpan77), and [Sebastian Beltran](https://github.com/bjohansebas).
|
||||||
56
node_modules/@types/cors/index.d.ts
generated
vendored
Normal file
56
node_modules/@types/cors/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import { IncomingHttpHeaders } from "http";
|
||||||
|
|
||||||
|
type StaticOrigin = boolean | string | RegExp | Array<boolean | string | RegExp>;
|
||||||
|
|
||||||
|
type CustomOrigin = (
|
||||||
|
requestOrigin: string | undefined,
|
||||||
|
callback: (err: Error | null, origin?: StaticOrigin) => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
declare namespace e {
|
||||||
|
interface CorsRequest {
|
||||||
|
method?: string | undefined;
|
||||||
|
headers: IncomingHttpHeaders;
|
||||||
|
}
|
||||||
|
interface CorsOptions {
|
||||||
|
/**
|
||||||
|
* @default '*'
|
||||||
|
*/
|
||||||
|
origin?: StaticOrigin | CustomOrigin | undefined;
|
||||||
|
/**
|
||||||
|
* @default 'GET,HEAD,PUT,PATCH,POST,DELETE'
|
||||||
|
*/
|
||||||
|
methods?: string | string[] | undefined;
|
||||||
|
allowedHeaders?: string | string[] | undefined;
|
||||||
|
exposedHeaders?: string | string[] | undefined;
|
||||||
|
credentials?: boolean | undefined;
|
||||||
|
maxAge?: number | undefined;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
preflightContinue?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* @default 204
|
||||||
|
*/
|
||||||
|
optionsSuccessStatus?: number | undefined;
|
||||||
|
}
|
||||||
|
type CorsOptionsDelegate<T extends CorsRequest = CorsRequest> = (
|
||||||
|
req: T,
|
||||||
|
callback: (err: Error | null, options?: CorsOptions) => void,
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare function e<T extends e.CorsRequest = e.CorsRequest>(
|
||||||
|
options?: e.CorsOptions | e.CorsOptionsDelegate<T>,
|
||||||
|
): (
|
||||||
|
req: T,
|
||||||
|
res: {
|
||||||
|
statusCode?: number | undefined;
|
||||||
|
setHeader(key: string, value: string): any;
|
||||||
|
end(): any;
|
||||||
|
},
|
||||||
|
next: (err?: any) => any,
|
||||||
|
) => void;
|
||||||
|
export = e;
|
||||||
38
node_modules/@types/cors/package.json
generated
vendored
Normal file
38
node_modules/@types/cors/package.json
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/cors",
|
||||||
|
"version": "2.8.19",
|
||||||
|
"description": "TypeScript definitions for cors",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/cors",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Alan Plum",
|
||||||
|
"githubUsername": "pluma",
|
||||||
|
"url": "https://github.com/pluma"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Gaurav Sharma",
|
||||||
|
"githubUsername": "gtpan77",
|
||||||
|
"url": "https://github.com/gtpan77"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sebastian Beltran",
|
||||||
|
"githubUsername": "bjohansebas",
|
||||||
|
"url": "https://github.com/bjohansebas"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/cors"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
},
|
||||||
|
"peerDependencies": {},
|
||||||
|
"typesPublisherContentHash": "a090e558c5f443573318c2955deecddc840bd8dfaac7cdedf31c7f6ede8d0b47",
|
||||||
|
"typeScriptVersion": "5.1"
|
||||||
|
}
|
||||||
21
node_modules/@types/ws/LICENSE
generated
vendored
Normal file
21
node_modules/@types/ws/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
15
node_modules/@types/ws/README.md
generated
vendored
Normal file
15
node_modules/@types/ws/README.md
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/ws`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for ws (https://github.com/websockets/ws).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ws.
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Tue, 01 Apr 2025 02:59:53 GMT
|
||||||
|
* Dependencies: [@types/node](https://npmjs.com/package/@types/node)
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Paul Loyd](https://github.com/loyd), [Margus Lamp](https://github.com/mlamp), [Philippe D'Alva](https://github.com/TitaneBoy), [reduckted](https://github.com/reduckted), [teidesu](https://github.com/teidesu), [Bartosz Wojtkowiak](https://github.com/wojtkowiak), [Kyle Hensel](https://github.com/k-yle), and [Samuel Skeen](https://github.com/cwadrupldijjit).
|
||||||
451
node_modules/@types/ws/index.d.mts
generated
vendored
Normal file
451
node_modules/@types/ws/index.d.mts
generated
vendored
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import { EventEmitter } from "events";
|
||||||
|
import {
|
||||||
|
Agent,
|
||||||
|
ClientRequest,
|
||||||
|
ClientRequestArgs,
|
||||||
|
IncomingMessage,
|
||||||
|
OutgoingHttpHeaders,
|
||||||
|
Server as HTTPServer,
|
||||||
|
} from "http";
|
||||||
|
import { Server as HTTPSServer } from "https";
|
||||||
|
import { createConnection } from "net";
|
||||||
|
import { Duplex, DuplexOptions } from "stream";
|
||||||
|
import { SecureContextOptions } from "tls";
|
||||||
|
import { URL } from "url";
|
||||||
|
import { ZlibOptions } from "zlib";
|
||||||
|
|
||||||
|
// can not get all overload of BufferConstructor['from'], need to copy all it's first arguments here
|
||||||
|
// https://github.com/microsoft/TypeScript/issues/32164
|
||||||
|
type BufferLike =
|
||||||
|
| string
|
||||||
|
| Buffer
|
||||||
|
| DataView
|
||||||
|
| number
|
||||||
|
| ArrayBufferView
|
||||||
|
| Uint8Array
|
||||||
|
| ArrayBuffer
|
||||||
|
| SharedArrayBuffer
|
||||||
|
| Blob
|
||||||
|
| readonly any[]
|
||||||
|
| readonly number[]
|
||||||
|
| { valueOf(): ArrayBuffer }
|
||||||
|
| { valueOf(): SharedArrayBuffer }
|
||||||
|
| { valueOf(): Uint8Array }
|
||||||
|
| { valueOf(): readonly number[] }
|
||||||
|
| { valueOf(): string }
|
||||||
|
| { [Symbol.toPrimitive](hint: string): string };
|
||||||
|
|
||||||
|
// WebSocket socket.
|
||||||
|
declare class WebSocket extends EventEmitter {
|
||||||
|
/** The connection is not yet open. */
|
||||||
|
static readonly CONNECTING: 0;
|
||||||
|
/** The connection is open and ready to communicate. */
|
||||||
|
static readonly OPEN: 1;
|
||||||
|
/** The connection is in the process of closing. */
|
||||||
|
static readonly CLOSING: 2;
|
||||||
|
/** The connection is closed. */
|
||||||
|
static readonly CLOSED: 3;
|
||||||
|
|
||||||
|
binaryType: "nodebuffer" | "arraybuffer" | "fragments";
|
||||||
|
readonly bufferedAmount: number;
|
||||||
|
readonly extensions: string;
|
||||||
|
/** Indicates whether the websocket is paused */
|
||||||
|
readonly isPaused: boolean;
|
||||||
|
readonly protocol: string;
|
||||||
|
/** The current state of the connection */
|
||||||
|
readonly readyState:
|
||||||
|
| typeof WebSocket.CONNECTING
|
||||||
|
| typeof WebSocket.OPEN
|
||||||
|
| typeof WebSocket.CLOSING
|
||||||
|
| typeof WebSocket.CLOSED;
|
||||||
|
readonly url: string;
|
||||||
|
|
||||||
|
/** The connection is not yet open. */
|
||||||
|
readonly CONNECTING: 0;
|
||||||
|
/** The connection is open and ready to communicate. */
|
||||||
|
readonly OPEN: 1;
|
||||||
|
/** The connection is in the process of closing. */
|
||||||
|
readonly CLOSING: 2;
|
||||||
|
/** The connection is closed. */
|
||||||
|
readonly CLOSED: 3;
|
||||||
|
|
||||||
|
onopen: ((event: WebSocket.Event) => void) | null;
|
||||||
|
onerror: ((event: WebSocket.ErrorEvent) => void) | null;
|
||||||
|
onclose: ((event: WebSocket.CloseEvent) => void) | null;
|
||||||
|
onmessage: ((event: WebSocket.MessageEvent) => void) | null;
|
||||||
|
|
||||||
|
constructor(address: null);
|
||||||
|
constructor(address: string | URL, options?: WebSocket.ClientOptions | ClientRequestArgs);
|
||||||
|
constructor(
|
||||||
|
address: string | URL,
|
||||||
|
protocols?: string | string[],
|
||||||
|
options?: WebSocket.ClientOptions | ClientRequestArgs,
|
||||||
|
);
|
||||||
|
|
||||||
|
close(code?: number, data?: string | Buffer): void;
|
||||||
|
ping(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
|
||||||
|
pong(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
|
||||||
|
// https://github.com/websockets/ws/issues/2076#issuecomment-1250354722
|
||||||
|
send(data: BufferLike, cb?: (err?: Error) => void): void;
|
||||||
|
send(
|
||||||
|
data: BufferLike,
|
||||||
|
options: {
|
||||||
|
mask?: boolean | undefined;
|
||||||
|
binary?: boolean | undefined;
|
||||||
|
compress?: boolean | undefined;
|
||||||
|
fin?: boolean | undefined;
|
||||||
|
},
|
||||||
|
cb?: (err?: Error) => void,
|
||||||
|
): void;
|
||||||
|
terminate(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause the websocket causing it to stop emitting events. Some events can still be
|
||||||
|
* emitted after this is called, until all buffered data is consumed. This method
|
||||||
|
* is a noop if the ready state is `CONNECTING` or `CLOSED`.
|
||||||
|
*/
|
||||||
|
pause(): void;
|
||||||
|
/**
|
||||||
|
* Make a paused socket resume emitting events. This method is a noop if the ready
|
||||||
|
* state is `CONNECTING` or `CLOSED`.
|
||||||
|
*/
|
||||||
|
resume(): void;
|
||||||
|
|
||||||
|
// HTML5 WebSocket events
|
||||||
|
addEventListener<K extends keyof WebSocket.WebSocketEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener:
|
||||||
|
| ((event: WebSocket.WebSocketEventMap[K]) => void)
|
||||||
|
| { handleEvent(event: WebSocket.WebSocketEventMap[K]): void },
|
||||||
|
options?: WebSocket.EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener<K extends keyof WebSocket.WebSocketEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener:
|
||||||
|
| ((event: WebSocket.WebSocketEventMap[K]) => void)
|
||||||
|
| { handleEvent(event: WebSocket.WebSocketEventMap[K]): void },
|
||||||
|
): void;
|
||||||
|
|
||||||
|
// Events
|
||||||
|
on(event: "close", listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
|
||||||
|
on(event: "error", listener: (this: WebSocket, error: Error) => void): this;
|
||||||
|
on(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
||||||
|
on(event: "message", listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
on(event: "open", listener: (this: WebSocket) => void): this;
|
||||||
|
on(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
|
||||||
|
on(event: "redirect", listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
||||||
|
on(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
on(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
once(event: "close", listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
|
||||||
|
once(event: "error", listener: (this: WebSocket, error: Error) => void): this;
|
||||||
|
once(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
||||||
|
once(event: "message", listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
once(event: "open", listener: (this: WebSocket) => void): this;
|
||||||
|
once(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
|
||||||
|
once(event: "redirect", listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
||||||
|
once(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
once(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
off(event: "close", listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
|
||||||
|
off(event: "error", listener: (this: WebSocket, error: Error) => void): this;
|
||||||
|
off(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
||||||
|
off(event: "message", listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
off(event: "open", listener: (this: WebSocket) => void): this;
|
||||||
|
off(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
|
||||||
|
off(event: "redirect", listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
||||||
|
off(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
off(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
addListener(event: "close", listener: (code: number, reason: Buffer) => void): this;
|
||||||
|
addListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
addListener(event: "upgrade", listener: (request: IncomingMessage) => void): this;
|
||||||
|
addListener(event: "message", listener: (data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
addListener(event: "open", listener: () => void): this;
|
||||||
|
addListener(event: "ping" | "pong", listener: (data: Buffer) => void): this;
|
||||||
|
addListener(event: "redirect", listener: (url: string, request: ClientRequest) => void): this;
|
||||||
|
addListener(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||||
|
|
||||||
|
removeListener(event: "close", listener: (code: number, reason: Buffer) => void): this;
|
||||||
|
removeListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
removeListener(event: "upgrade", listener: (request: IncomingMessage) => void): this;
|
||||||
|
removeListener(event: "message", listener: (data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
removeListener(event: "open", listener: () => void): this;
|
||||||
|
removeListener(event: "ping" | "pong", listener: (data: Buffer) => void): this;
|
||||||
|
removeListener(event: "redirect", listener: (url: string, request: ClientRequest) => void): this;
|
||||||
|
removeListener(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare namespace WebSocket {
|
||||||
|
/**
|
||||||
|
* Data represents the raw message payload received over the WebSocket.
|
||||||
|
*/
|
||||||
|
type RawData = Buffer | ArrayBuffer | Buffer[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data represents the message payload received over the WebSocket.
|
||||||
|
*/
|
||||||
|
type Data = string | Buffer | ArrayBuffer | Buffer[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CertMeta represents the accepted types for certificate & key data.
|
||||||
|
*/
|
||||||
|
type CertMeta = string | string[] | Buffer | Buffer[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VerifyClientCallbackSync is a synchronous callback used to inspect the
|
||||||
|
* incoming message. The return value (boolean) of the function determines
|
||||||
|
* whether or not to accept the handshake.
|
||||||
|
*/
|
||||||
|
type VerifyClientCallbackSync<Request extends IncomingMessage = IncomingMessage> = (info: {
|
||||||
|
origin: string;
|
||||||
|
secure: boolean;
|
||||||
|
req: Request;
|
||||||
|
}) => boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VerifyClientCallbackAsync is an asynchronous callback used to inspect the
|
||||||
|
* incoming message. The return value (boolean) of the function determines
|
||||||
|
* whether or not to accept the handshake.
|
||||||
|
*/
|
||||||
|
type VerifyClientCallbackAsync<Request extends IncomingMessage = IncomingMessage> = (
|
||||||
|
info: { origin: string; secure: boolean; req: Request },
|
||||||
|
callback: (res: boolean, code?: number, message?: string, headers?: OutgoingHttpHeaders) => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FinishRequestCallback is a callback for last minute customization of the
|
||||||
|
* headers. If finishRequest is set, then it has the responsibility to call
|
||||||
|
* request.end() once it is done setting request headers.
|
||||||
|
*/
|
||||||
|
type FinishRequestCallback = (request: ClientRequest, websocket: WebSocket) => void;
|
||||||
|
|
||||||
|
interface ClientOptions extends SecureContextOptions {
|
||||||
|
protocol?: string | undefined;
|
||||||
|
followRedirects?: boolean | undefined;
|
||||||
|
generateMask?(mask: Buffer): void;
|
||||||
|
handshakeTimeout?: number | undefined;
|
||||||
|
maxRedirects?: number | undefined;
|
||||||
|
perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined;
|
||||||
|
localAddress?: string | undefined;
|
||||||
|
protocolVersion?: number | undefined;
|
||||||
|
headers?: { [key: string]: string } | undefined;
|
||||||
|
origin?: string | undefined;
|
||||||
|
agent?: Agent | undefined;
|
||||||
|
host?: string | undefined;
|
||||||
|
family?: number | undefined;
|
||||||
|
checkServerIdentity?(servername: string, cert: CertMeta): boolean;
|
||||||
|
rejectUnauthorized?: boolean | undefined;
|
||||||
|
allowSynchronousEvents?: boolean | undefined;
|
||||||
|
autoPong?: boolean | undefined;
|
||||||
|
maxPayload?: number | undefined;
|
||||||
|
skipUTF8Validation?: boolean | undefined;
|
||||||
|
createConnection?: typeof createConnection | undefined;
|
||||||
|
finishRequest?: FinishRequestCallback | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PerMessageDeflateOptions {
|
||||||
|
serverNoContextTakeover?: boolean | undefined;
|
||||||
|
clientNoContextTakeover?: boolean | undefined;
|
||||||
|
serverMaxWindowBits?: number | undefined;
|
||||||
|
clientMaxWindowBits?: number | undefined;
|
||||||
|
zlibDeflateOptions?:
|
||||||
|
| {
|
||||||
|
flush?: number | undefined;
|
||||||
|
finishFlush?: number | undefined;
|
||||||
|
chunkSize?: number | undefined;
|
||||||
|
windowBits?: number | undefined;
|
||||||
|
level?: number | undefined;
|
||||||
|
memLevel?: number | undefined;
|
||||||
|
strategy?: number | undefined;
|
||||||
|
dictionary?: Buffer | Buffer[] | DataView | undefined;
|
||||||
|
info?: boolean | undefined;
|
||||||
|
}
|
||||||
|
| undefined;
|
||||||
|
zlibInflateOptions?: ZlibOptions | undefined;
|
||||||
|
threshold?: number | undefined;
|
||||||
|
concurrencyLimit?: number | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Event {
|
||||||
|
type: string;
|
||||||
|
target: WebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ErrorEvent {
|
||||||
|
error: any;
|
||||||
|
message: string;
|
||||||
|
type: string;
|
||||||
|
target: WebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CloseEvent {
|
||||||
|
wasClean: boolean;
|
||||||
|
code: number;
|
||||||
|
reason: string;
|
||||||
|
type: string;
|
||||||
|
target: WebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MessageEvent {
|
||||||
|
data: Data;
|
||||||
|
type: string;
|
||||||
|
target: WebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WebSocketEventMap {
|
||||||
|
open: Event;
|
||||||
|
error: ErrorEvent;
|
||||||
|
close: CloseEvent;
|
||||||
|
message: MessageEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EventListenerOptions {
|
||||||
|
once?: boolean | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ServerOptions<
|
||||||
|
U extends typeof WebSocket = typeof WebSocket,
|
||||||
|
V extends typeof IncomingMessage = typeof IncomingMessage,
|
||||||
|
> {
|
||||||
|
host?: string | undefined;
|
||||||
|
port?: number | undefined;
|
||||||
|
backlog?: number | undefined;
|
||||||
|
server?: HTTPServer<V> | HTTPSServer<V> | undefined;
|
||||||
|
verifyClient?:
|
||||||
|
| VerifyClientCallbackAsync<InstanceType<V>>
|
||||||
|
| VerifyClientCallbackSync<InstanceType<V>>
|
||||||
|
| undefined;
|
||||||
|
handleProtocols?: (protocols: Set<string>, request: InstanceType<V>) => string | false;
|
||||||
|
path?: string | undefined;
|
||||||
|
noServer?: boolean | undefined;
|
||||||
|
allowSynchronousEvents?: boolean | undefined;
|
||||||
|
autoPong?: boolean | undefined;
|
||||||
|
clientTracking?: boolean | undefined;
|
||||||
|
perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined;
|
||||||
|
maxPayload?: number | undefined;
|
||||||
|
skipUTF8Validation?: boolean | undefined;
|
||||||
|
WebSocket?: U | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddressInfo {
|
||||||
|
address: string;
|
||||||
|
family: string;
|
||||||
|
port: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export import AddressInfo = WebSocket.AddressInfo;
|
||||||
|
export import CertMeta = WebSocket.CertMeta;
|
||||||
|
export import ClientOptions = WebSocket.ClientOptions;
|
||||||
|
export import CloseEvent = WebSocket.CloseEvent;
|
||||||
|
export import Data = WebSocket.Data;
|
||||||
|
export import ErrorEvent = WebSocket.ErrorEvent;
|
||||||
|
export import Event = WebSocket.Event;
|
||||||
|
export import EventListenerOptions = WebSocket.EventListenerOptions;
|
||||||
|
export import FinishRequestCallback = WebSocket.FinishRequestCallback;
|
||||||
|
export import MessageEvent = WebSocket.MessageEvent;
|
||||||
|
export import PerMessageDeflateOptions = WebSocket.PerMessageDeflateOptions;
|
||||||
|
export import RawData = WebSocket.RawData;
|
||||||
|
export import ServerOptions = WebSocket.ServerOptions;
|
||||||
|
export import VerifyClientCallbackAsync = WebSocket.VerifyClientCallbackAsync;
|
||||||
|
export import VerifyClientCallbackSync = WebSocket.VerifyClientCallbackSync;
|
||||||
|
|
||||||
|
// WebSocket Server
|
||||||
|
declare class Server<
|
||||||
|
T extends typeof WebSocket = typeof WebSocket,
|
||||||
|
U extends typeof IncomingMessage = typeof IncomingMessage,
|
||||||
|
> extends EventEmitter {
|
||||||
|
options: WebSocket.ServerOptions<T, U>;
|
||||||
|
path: string;
|
||||||
|
clients: Set<InstanceType<T>>;
|
||||||
|
|
||||||
|
constructor(options?: WebSocket.ServerOptions<T, U>, callback?: () => void);
|
||||||
|
|
||||||
|
address(): WebSocket.AddressInfo | string | null;
|
||||||
|
close(cb?: (err?: Error) => void): void;
|
||||||
|
handleUpgrade(
|
||||||
|
request: InstanceType<U>,
|
||||||
|
socket: Duplex,
|
||||||
|
upgradeHead: Buffer,
|
||||||
|
callback: (client: InstanceType<T>, request: InstanceType<U>) => void,
|
||||||
|
): void;
|
||||||
|
shouldHandle(request: InstanceType<U>): boolean | Promise<boolean>;
|
||||||
|
|
||||||
|
// Events
|
||||||
|
on(event: "connection", cb: (this: Server<T>, websocket: InstanceType<T>, request: InstanceType<U>) => void): this;
|
||||||
|
on(event: "error", cb: (this: Server<T>, error: Error) => void): this;
|
||||||
|
on(event: "headers", cb: (this: Server<T>, headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
on(event: "close" | "listening", cb: (this: Server<T>) => void): this;
|
||||||
|
on(
|
||||||
|
event: "wsClientError",
|
||||||
|
cb: (this: Server<T>, error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
on(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
once(
|
||||||
|
event: "connection",
|
||||||
|
cb: (this: Server<T>, websocket: InstanceType<T>, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
once(event: "error", cb: (this: Server<T>, error: Error) => void): this;
|
||||||
|
once(event: "headers", cb: (this: Server<T>, headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
once(event: "close" | "listening", cb: (this: Server<T>) => void): this;
|
||||||
|
once(
|
||||||
|
event: "wsClientError",
|
||||||
|
cb: (this: Server<T>, error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
once(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
off(event: "connection", cb: (this: Server<T>, websocket: InstanceType<T>, request: InstanceType<U>) => void): this;
|
||||||
|
off(event: "error", cb: (this: Server<T>, error: Error) => void): this;
|
||||||
|
off(event: "headers", cb: (this: Server<T>, headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
off(event: "close" | "listening", cb: (this: Server<T>) => void): this;
|
||||||
|
off(
|
||||||
|
event: "wsClientError",
|
||||||
|
cb: (this: Server<T>, error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
off(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
addListener(event: "connection", cb: (websocket: InstanceType<T>, request: InstanceType<U>) => void): this;
|
||||||
|
addListener(event: "error", cb: (error: Error) => void): this;
|
||||||
|
addListener(event: "headers", cb: (headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
addListener(event: "close" | "listening", cb: () => void): this;
|
||||||
|
addListener(event: "wsClientError", cb: (error: Error, socket: Duplex, request: InstanceType<U>) => void): this;
|
||||||
|
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||||
|
|
||||||
|
removeListener(event: "connection", cb: (websocket: InstanceType<T>, request: InstanceType<U>) => void): this;
|
||||||
|
removeListener(event: "error", cb: (error: Error) => void): this;
|
||||||
|
removeListener(event: "headers", cb: (headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
removeListener(event: "close" | "listening", cb: () => void): this;
|
||||||
|
removeListener(event: "wsClientError", cb: (error: Error, socket: Duplex, request: InstanceType<U>) => void): this;
|
||||||
|
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||||
|
}
|
||||||
|
export { type Server };
|
||||||
|
|
||||||
|
export const WebSocketServer: typeof Server;
|
||||||
|
export interface WebSocketServer extends Server {} // eslint-disable-line @typescript-eslint/no-empty-interface
|
||||||
|
|
||||||
|
// WebSocket stream
|
||||||
|
export function createWebSocketStream(websocket: WebSocket, options?: DuplexOptions): Duplex;
|
||||||
|
|
||||||
|
export default WebSocket;
|
||||||
|
export { WebSocket };
|
||||||
445
node_modules/@types/ws/index.d.ts
generated
vendored
Normal file
445
node_modules/@types/ws/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import { EventEmitter } from "events";
|
||||||
|
import {
|
||||||
|
Agent,
|
||||||
|
ClientRequest,
|
||||||
|
ClientRequestArgs,
|
||||||
|
IncomingMessage,
|
||||||
|
OutgoingHttpHeaders,
|
||||||
|
Server as HTTPServer,
|
||||||
|
} from "http";
|
||||||
|
import { Server as HTTPSServer } from "https";
|
||||||
|
import { createConnection } from "net";
|
||||||
|
import { Duplex, DuplexOptions } from "stream";
|
||||||
|
import { SecureContextOptions } from "tls";
|
||||||
|
import { URL } from "url";
|
||||||
|
import { ZlibOptions } from "zlib";
|
||||||
|
|
||||||
|
// can not get all overload of BufferConstructor['from'], need to copy all it's first arguments here
|
||||||
|
// https://github.com/microsoft/TypeScript/issues/32164
|
||||||
|
type BufferLike =
|
||||||
|
| string
|
||||||
|
| Buffer
|
||||||
|
| DataView
|
||||||
|
| number
|
||||||
|
| ArrayBufferView
|
||||||
|
| Uint8Array
|
||||||
|
| ArrayBuffer
|
||||||
|
| SharedArrayBuffer
|
||||||
|
| Blob
|
||||||
|
| readonly any[]
|
||||||
|
| readonly number[]
|
||||||
|
| { valueOf(): ArrayBuffer }
|
||||||
|
| { valueOf(): SharedArrayBuffer }
|
||||||
|
| { valueOf(): Uint8Array }
|
||||||
|
| { valueOf(): readonly number[] }
|
||||||
|
| { valueOf(): string }
|
||||||
|
| { [Symbol.toPrimitive](hint: string): string };
|
||||||
|
|
||||||
|
// WebSocket socket.
|
||||||
|
declare class WebSocket extends EventEmitter {
|
||||||
|
/** The connection is not yet open. */
|
||||||
|
static readonly CONNECTING: 0;
|
||||||
|
/** The connection is open and ready to communicate. */
|
||||||
|
static readonly OPEN: 1;
|
||||||
|
/** The connection is in the process of closing. */
|
||||||
|
static readonly CLOSING: 2;
|
||||||
|
/** The connection is closed. */
|
||||||
|
static readonly CLOSED: 3;
|
||||||
|
|
||||||
|
binaryType: "nodebuffer" | "arraybuffer" | "fragments";
|
||||||
|
readonly bufferedAmount: number;
|
||||||
|
readonly extensions: string;
|
||||||
|
/** Indicates whether the websocket is paused */
|
||||||
|
readonly isPaused: boolean;
|
||||||
|
readonly protocol: string;
|
||||||
|
/** The current state of the connection */
|
||||||
|
readonly readyState:
|
||||||
|
| typeof WebSocket.CONNECTING
|
||||||
|
| typeof WebSocket.OPEN
|
||||||
|
| typeof WebSocket.CLOSING
|
||||||
|
| typeof WebSocket.CLOSED;
|
||||||
|
readonly url: string;
|
||||||
|
|
||||||
|
/** The connection is not yet open. */
|
||||||
|
readonly CONNECTING: 0;
|
||||||
|
/** The connection is open and ready to communicate. */
|
||||||
|
readonly OPEN: 1;
|
||||||
|
/** The connection is in the process of closing. */
|
||||||
|
readonly CLOSING: 2;
|
||||||
|
/** The connection is closed. */
|
||||||
|
readonly CLOSED: 3;
|
||||||
|
|
||||||
|
onopen: ((event: WebSocket.Event) => void) | null;
|
||||||
|
onerror: ((event: WebSocket.ErrorEvent) => void) | null;
|
||||||
|
onclose: ((event: WebSocket.CloseEvent) => void) | null;
|
||||||
|
onmessage: ((event: WebSocket.MessageEvent) => void) | null;
|
||||||
|
|
||||||
|
constructor(address: null);
|
||||||
|
constructor(address: string | URL, options?: WebSocket.ClientOptions | ClientRequestArgs);
|
||||||
|
constructor(
|
||||||
|
address: string | URL,
|
||||||
|
protocols?: string | string[],
|
||||||
|
options?: WebSocket.ClientOptions | ClientRequestArgs,
|
||||||
|
);
|
||||||
|
|
||||||
|
close(code?: number, data?: string | Buffer): void;
|
||||||
|
ping(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
|
||||||
|
pong(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
|
||||||
|
// https://github.com/websockets/ws/issues/2076#issuecomment-1250354722
|
||||||
|
send(data: BufferLike, cb?: (err?: Error) => void): void;
|
||||||
|
send(
|
||||||
|
data: BufferLike,
|
||||||
|
options: {
|
||||||
|
mask?: boolean | undefined;
|
||||||
|
binary?: boolean | undefined;
|
||||||
|
compress?: boolean | undefined;
|
||||||
|
fin?: boolean | undefined;
|
||||||
|
},
|
||||||
|
cb?: (err?: Error) => void,
|
||||||
|
): void;
|
||||||
|
terminate(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause the websocket causing it to stop emitting events. Some events can still be
|
||||||
|
* emitted after this is called, until all buffered data is consumed. This method
|
||||||
|
* is a noop if the ready state is `CONNECTING` or `CLOSED`.
|
||||||
|
*/
|
||||||
|
pause(): void;
|
||||||
|
/**
|
||||||
|
* Make a paused socket resume emitting events. This method is a noop if the ready
|
||||||
|
* state is `CONNECTING` or `CLOSED`.
|
||||||
|
*/
|
||||||
|
resume(): void;
|
||||||
|
|
||||||
|
// HTML5 WebSocket events
|
||||||
|
addEventListener<K extends keyof WebSocket.WebSocketEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener:
|
||||||
|
| ((event: WebSocket.WebSocketEventMap[K]) => void)
|
||||||
|
| { handleEvent(event: WebSocket.WebSocketEventMap[K]): void },
|
||||||
|
options?: WebSocket.EventListenerOptions,
|
||||||
|
): void;
|
||||||
|
removeEventListener<K extends keyof WebSocket.WebSocketEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener:
|
||||||
|
| ((event: WebSocket.WebSocketEventMap[K]) => void)
|
||||||
|
| { handleEvent(event: WebSocket.WebSocketEventMap[K]): void },
|
||||||
|
): void;
|
||||||
|
|
||||||
|
// Events
|
||||||
|
on(event: "close", listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
|
||||||
|
on(event: "error", listener: (this: WebSocket, error: Error) => void): this;
|
||||||
|
on(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
||||||
|
on(event: "message", listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
on(event: "open", listener: (this: WebSocket) => void): this;
|
||||||
|
on(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
|
||||||
|
on(event: "redirect", listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
||||||
|
on(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
on(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
once(event: "close", listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
|
||||||
|
once(event: "error", listener: (this: WebSocket, error: Error) => void): this;
|
||||||
|
once(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
||||||
|
once(event: "message", listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
once(event: "open", listener: (this: WebSocket) => void): this;
|
||||||
|
once(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
|
||||||
|
once(event: "redirect", listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
||||||
|
once(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
once(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
off(event: "close", listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
|
||||||
|
off(event: "error", listener: (this: WebSocket, error: Error) => void): this;
|
||||||
|
off(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
||||||
|
off(event: "message", listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
off(event: "open", listener: (this: WebSocket) => void): this;
|
||||||
|
off(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
|
||||||
|
off(event: "redirect", listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
||||||
|
off(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
off(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
addListener(event: "close", listener: (code: number, reason: Buffer) => void): this;
|
||||||
|
addListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
addListener(event: "upgrade", listener: (request: IncomingMessage) => void): this;
|
||||||
|
addListener(event: "message", listener: (data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
addListener(event: "open", listener: () => void): this;
|
||||||
|
addListener(event: "ping" | "pong", listener: (data: Buffer) => void): this;
|
||||||
|
addListener(event: "redirect", listener: (url: string, request: ClientRequest) => void): this;
|
||||||
|
addListener(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||||
|
|
||||||
|
removeListener(event: "close", listener: (code: number, reason: Buffer) => void): this;
|
||||||
|
removeListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
removeListener(event: "upgrade", listener: (request: IncomingMessage) => void): this;
|
||||||
|
removeListener(event: "message", listener: (data: WebSocket.RawData, isBinary: boolean) => void): this;
|
||||||
|
removeListener(event: "open", listener: () => void): this;
|
||||||
|
removeListener(event: "ping" | "pong", listener: (data: Buffer) => void): this;
|
||||||
|
removeListener(event: "redirect", listener: (url: string, request: ClientRequest) => void): this;
|
||||||
|
removeListener(
|
||||||
|
event: "unexpected-response",
|
||||||
|
listener: (request: ClientRequest, response: IncomingMessage) => void,
|
||||||
|
): this;
|
||||||
|
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const WebSocketAlias: typeof WebSocket;
|
||||||
|
interface WebSocketAlias extends WebSocket {} // eslint-disable-line @typescript-eslint/no-empty-interface
|
||||||
|
|
||||||
|
declare namespace WebSocket {
|
||||||
|
/**
|
||||||
|
* Data represents the raw message payload received over the WebSocket.
|
||||||
|
*/
|
||||||
|
type RawData = Buffer | ArrayBuffer | Buffer[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data represents the message payload received over the WebSocket.
|
||||||
|
*/
|
||||||
|
type Data = string | Buffer | ArrayBuffer | Buffer[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CertMeta represents the accepted types for certificate & key data.
|
||||||
|
*/
|
||||||
|
type CertMeta = string | string[] | Buffer | Buffer[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VerifyClientCallbackSync is a synchronous callback used to inspect the
|
||||||
|
* incoming message. The return value (boolean) of the function determines
|
||||||
|
* whether or not to accept the handshake.
|
||||||
|
*/
|
||||||
|
type VerifyClientCallbackSync<Request extends IncomingMessage = IncomingMessage> = (info: {
|
||||||
|
origin: string;
|
||||||
|
secure: boolean;
|
||||||
|
req: Request;
|
||||||
|
}) => boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VerifyClientCallbackAsync is an asynchronous callback used to inspect the
|
||||||
|
* incoming message. The return value (boolean) of the function determines
|
||||||
|
* whether or not to accept the handshake.
|
||||||
|
*/
|
||||||
|
type VerifyClientCallbackAsync<Request extends IncomingMessage = IncomingMessage> = (
|
||||||
|
info: { origin: string; secure: boolean; req: Request },
|
||||||
|
callback: (res: boolean, code?: number, message?: string, headers?: OutgoingHttpHeaders) => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FinishRequestCallback is a callback for last minute customization of the
|
||||||
|
* headers. If finishRequest is set, then it has the responsibility to call
|
||||||
|
* request.end() once it is done setting request headers.
|
||||||
|
*/
|
||||||
|
type FinishRequestCallback = (request: ClientRequest, websocket: WebSocket) => void;
|
||||||
|
|
||||||
|
interface ClientOptions extends SecureContextOptions {
|
||||||
|
protocol?: string | undefined;
|
||||||
|
followRedirects?: boolean | undefined;
|
||||||
|
generateMask?(mask: Buffer): void;
|
||||||
|
handshakeTimeout?: number | undefined;
|
||||||
|
maxRedirects?: number | undefined;
|
||||||
|
perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined;
|
||||||
|
localAddress?: string | undefined;
|
||||||
|
protocolVersion?: number | undefined;
|
||||||
|
headers?: { [key: string]: string } | undefined;
|
||||||
|
origin?: string | undefined;
|
||||||
|
agent?: Agent | undefined;
|
||||||
|
host?: string | undefined;
|
||||||
|
family?: number | undefined;
|
||||||
|
checkServerIdentity?(servername: string, cert: CertMeta): boolean;
|
||||||
|
rejectUnauthorized?: boolean | undefined;
|
||||||
|
allowSynchronousEvents?: boolean | undefined;
|
||||||
|
autoPong?: boolean | undefined;
|
||||||
|
maxPayload?: number | undefined;
|
||||||
|
skipUTF8Validation?: boolean | undefined;
|
||||||
|
createConnection?: typeof createConnection | undefined;
|
||||||
|
finishRequest?: FinishRequestCallback | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PerMessageDeflateOptions {
|
||||||
|
serverNoContextTakeover?: boolean | undefined;
|
||||||
|
clientNoContextTakeover?: boolean | undefined;
|
||||||
|
serverMaxWindowBits?: number | undefined;
|
||||||
|
clientMaxWindowBits?: number | undefined;
|
||||||
|
zlibDeflateOptions?: {
|
||||||
|
flush?: number | undefined;
|
||||||
|
finishFlush?: number | undefined;
|
||||||
|
chunkSize?: number | undefined;
|
||||||
|
windowBits?: number | undefined;
|
||||||
|
level?: number | undefined;
|
||||||
|
memLevel?: number | undefined;
|
||||||
|
strategy?: number | undefined;
|
||||||
|
dictionary?: Buffer | Buffer[] | DataView | undefined;
|
||||||
|
info?: boolean | undefined;
|
||||||
|
} | undefined;
|
||||||
|
zlibInflateOptions?: ZlibOptions | undefined;
|
||||||
|
threshold?: number | undefined;
|
||||||
|
concurrencyLimit?: number | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Event {
|
||||||
|
type: string;
|
||||||
|
target: WebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ErrorEvent {
|
||||||
|
error: any;
|
||||||
|
message: string;
|
||||||
|
type: string;
|
||||||
|
target: WebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CloseEvent {
|
||||||
|
wasClean: boolean;
|
||||||
|
code: number;
|
||||||
|
reason: string;
|
||||||
|
type: string;
|
||||||
|
target: WebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MessageEvent {
|
||||||
|
data: Data;
|
||||||
|
type: string;
|
||||||
|
target: WebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WebSocketEventMap {
|
||||||
|
open: Event;
|
||||||
|
error: ErrorEvent;
|
||||||
|
close: CloseEvent;
|
||||||
|
message: MessageEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EventListenerOptions {
|
||||||
|
once?: boolean | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ServerOptions<
|
||||||
|
U extends typeof WebSocket.WebSocket = typeof WebSocket.WebSocket,
|
||||||
|
V extends typeof IncomingMessage = typeof IncomingMessage,
|
||||||
|
> {
|
||||||
|
host?: string | undefined;
|
||||||
|
port?: number | undefined;
|
||||||
|
backlog?: number | undefined;
|
||||||
|
server?: HTTPServer<V> | HTTPSServer<V> | undefined;
|
||||||
|
verifyClient?:
|
||||||
|
| VerifyClientCallbackAsync<InstanceType<V>>
|
||||||
|
| VerifyClientCallbackSync<InstanceType<V>>
|
||||||
|
| undefined;
|
||||||
|
handleProtocols?: (protocols: Set<string>, request: InstanceType<V>) => string | false;
|
||||||
|
path?: string | undefined;
|
||||||
|
noServer?: boolean | undefined;
|
||||||
|
allowSynchronousEvents?: boolean | undefined;
|
||||||
|
autoPong?: boolean | undefined;
|
||||||
|
clientTracking?: boolean | undefined;
|
||||||
|
perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined;
|
||||||
|
maxPayload?: number | undefined;
|
||||||
|
skipUTF8Validation?: boolean | undefined;
|
||||||
|
WebSocket?: U | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddressInfo {
|
||||||
|
address: string;
|
||||||
|
family: string;
|
||||||
|
port: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebSocket Server
|
||||||
|
class Server<
|
||||||
|
T extends typeof WebSocket.WebSocket = typeof WebSocket.WebSocket,
|
||||||
|
U extends typeof IncomingMessage = typeof IncomingMessage,
|
||||||
|
> extends EventEmitter {
|
||||||
|
options: ServerOptions<T, U>;
|
||||||
|
path: string;
|
||||||
|
clients: Set<InstanceType<T>>;
|
||||||
|
|
||||||
|
constructor(options?: ServerOptions<T, U>, callback?: () => void);
|
||||||
|
|
||||||
|
address(): AddressInfo | string | null;
|
||||||
|
close(cb?: (err?: Error) => void): void;
|
||||||
|
handleUpgrade(
|
||||||
|
request: InstanceType<U>,
|
||||||
|
socket: Duplex,
|
||||||
|
upgradeHead: Buffer,
|
||||||
|
callback: (client: InstanceType<T>, request: InstanceType<U>) => void,
|
||||||
|
): void;
|
||||||
|
shouldHandle(request: InstanceType<U>): boolean | Promise<boolean>;
|
||||||
|
|
||||||
|
// Events
|
||||||
|
on(
|
||||||
|
event: "connection",
|
||||||
|
cb: (this: Server<T>, websocket: InstanceType<T>, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
on(event: "error", cb: (this: Server<T>, error: Error) => void): this;
|
||||||
|
on(event: "headers", cb: (this: Server<T>, headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
on(event: "close" | "listening", cb: (this: Server<T>) => void): this;
|
||||||
|
on(
|
||||||
|
event: "wsClientError",
|
||||||
|
cb: (this: Server<T>, error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
on(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
once(
|
||||||
|
event: "connection",
|
||||||
|
cb: (this: Server<T>, websocket: InstanceType<T>, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
once(event: "error", cb: (this: Server<T>, error: Error) => void): this;
|
||||||
|
once(event: "headers", cb: (this: Server<T>, headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
once(event: "close" | "listening", cb: (this: Server<T>) => void): this;
|
||||||
|
once(
|
||||||
|
event: "wsClientError",
|
||||||
|
cb: (this: Server<T>, error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
once(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
off(
|
||||||
|
event: "connection",
|
||||||
|
cb: (this: Server<T>, socket: InstanceType<T>, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
off(event: "error", cb: (this: Server<T>, error: Error) => void): this;
|
||||||
|
off(event: "headers", cb: (this: Server<T>, headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
off(event: "close" | "listening", cb: (this: Server<T>) => void): this;
|
||||||
|
off(
|
||||||
|
event: "wsClientError",
|
||||||
|
cb: (this: Server<T>, error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
off(event: string | symbol, listener: (this: Server<T>, ...args: any[]) => void): this;
|
||||||
|
|
||||||
|
addListener(event: "connection", cb: (websocket: InstanceType<T>, request: InstanceType<U>) => void): this;
|
||||||
|
addListener(event: "error", cb: (error: Error) => void): this;
|
||||||
|
addListener(event: "headers", cb: (headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
addListener(event: "close" | "listening", cb: () => void): this;
|
||||||
|
addListener(event: "wsClientError", cb: (error: Error, socket: Duplex, request: InstanceType<U>) => void): this;
|
||||||
|
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||||
|
|
||||||
|
removeListener(event: "connection", cb: (websocket: InstanceType<T>, request: InstanceType<U>) => void): this;
|
||||||
|
removeListener(event: "error", cb: (error: Error) => void): this;
|
||||||
|
removeListener(event: "headers", cb: (headers: string[], request: InstanceType<U>) => void): this;
|
||||||
|
removeListener(event: "close" | "listening", cb: () => void): this;
|
||||||
|
removeListener(
|
||||||
|
event: "wsClientError",
|
||||||
|
cb: (error: Error, socket: Duplex, request: InstanceType<U>) => void,
|
||||||
|
): this;
|
||||||
|
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WebSocketServer: typeof Server;
|
||||||
|
interface WebSocketServer extends Server {} // eslint-disable-line @typescript-eslint/no-empty-interface
|
||||||
|
const WebSocket: typeof WebSocketAlias;
|
||||||
|
interface WebSocket extends WebSocketAlias {} // eslint-disable-line @typescript-eslint/no-empty-interface
|
||||||
|
|
||||||
|
// WebSocket stream
|
||||||
|
function createWebSocketStream(websocket: WebSocket, options?: DuplexOptions): Duplex;
|
||||||
|
}
|
||||||
|
|
||||||
|
export = WebSocket;
|
||||||
72
node_modules/@types/ws/package.json
generated
vendored
Normal file
72
node_modules/@types/ws/package.json
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/ws",
|
||||||
|
"version": "8.18.1",
|
||||||
|
"description": "TypeScript definitions for ws",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ws",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Paul Loyd",
|
||||||
|
"githubUsername": "loyd",
|
||||||
|
"url": "https://github.com/loyd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Margus Lamp",
|
||||||
|
"githubUsername": "mlamp",
|
||||||
|
"url": "https://github.com/mlamp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Philippe D'Alva",
|
||||||
|
"githubUsername": "TitaneBoy",
|
||||||
|
"url": "https://github.com/TitaneBoy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "reduckted",
|
||||||
|
"githubUsername": "reduckted",
|
||||||
|
"url": "https://github.com/reduckted"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "teidesu",
|
||||||
|
"githubUsername": "teidesu",
|
||||||
|
"url": "https://github.com/teidesu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bartosz Wojtkowiak",
|
||||||
|
"githubUsername": "wojtkowiak",
|
||||||
|
"url": "https://github.com/wojtkowiak"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kyle Hensel",
|
||||||
|
"githubUsername": "k-yle",
|
||||||
|
"url": "https://github.com/k-yle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Samuel Skeen",
|
||||||
|
"githubUsername": "cwadrupldijjit",
|
||||||
|
"url": "https://github.com/cwadrupldijjit"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": {
|
||||||
|
"import": "./index.d.mts",
|
||||||
|
"default": "./index.d.ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/ws"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
},
|
||||||
|
"peerDependencies": {},
|
||||||
|
"typesPublisherContentHash": "043c83a4bb92503ab01243879ee715fb6db391090d10883c5a2eb72099d22724",
|
||||||
|
"typeScriptVersion": "5.1"
|
||||||
|
}
|
||||||
16
node_modules/base64id/CHANGELOG.md
generated
vendored
Normal file
16
node_modules/base64id/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# [2.0.0](https://github.com/faeldt/base64id/compare/1.0.0...2.0.0) (2019-05-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* **buffer:** replace deprecated Buffer constructor usage ([#11](https://github.com/faeldt/base64id/issues/11)) ([ccfba54](https://github.com/faeldt/base64id/commit/ccfba54))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **buffer:** drop support for Node.js ≤ 4.4.x and 5.0.0 - 5.9.x
|
||||||
|
|
||||||
|
See: https://nodejs.org/en/docs/guides/buffer-constructor-deprecation/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
22
node_modules/base64id/LICENSE
generated
vendored
Normal file
22
node_modules/base64id/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2012-2016 Kristian Faeldt <faeldt_kristian@cyberagent.co.jp>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
18
node_modules/base64id/README.md
generated
vendored
Normal file
18
node_modules/base64id/README.md
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
base64id
|
||||||
|
========
|
||||||
|
|
||||||
|
Node.js module that generates a base64 id.
|
||||||
|
|
||||||
|
Uses crypto.randomBytes when available, falls back to unsafe methods for node.js <= 0.4.
|
||||||
|
|
||||||
|
To increase performance, random bytes are buffered to minimize the number of synchronous calls to crypto.randomBytes.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
$ npm install base64id
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
var base64id = require('base64id');
|
||||||
|
|
||||||
|
var id = base64id.generateId();
|
||||||
103
node_modules/base64id/lib/base64id.js
generated
vendored
Normal file
103
node_modules/base64id/lib/base64id.js
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*!
|
||||||
|
* base64id v0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies
|
||||||
|
*/
|
||||||
|
|
||||||
|
var crypto = require('crypto');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Base64Id = function() { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get random bytes
|
||||||
|
*
|
||||||
|
* Uses a buffer if available, falls back to crypto.randomBytes
|
||||||
|
*/
|
||||||
|
|
||||||
|
Base64Id.prototype.getRandomBytes = function(bytes) {
|
||||||
|
|
||||||
|
var BUFFER_SIZE = 4096
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
bytes = bytes || 12;
|
||||||
|
|
||||||
|
if (bytes > BUFFER_SIZE) {
|
||||||
|
return crypto.randomBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytesInBuffer = parseInt(BUFFER_SIZE/bytes);
|
||||||
|
var threshold = parseInt(bytesInBuffer*0.85);
|
||||||
|
|
||||||
|
if (!threshold) {
|
||||||
|
return crypto.randomBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.bytesBufferIndex == null) {
|
||||||
|
this.bytesBufferIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.bytesBufferIndex == bytesInBuffer) {
|
||||||
|
this.bytesBuffer = null;
|
||||||
|
this.bytesBufferIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No buffered bytes available or index above threshold
|
||||||
|
if (this.bytesBufferIndex == -1 || this.bytesBufferIndex > threshold) {
|
||||||
|
|
||||||
|
if (!this.isGeneratingBytes) {
|
||||||
|
this.isGeneratingBytes = true;
|
||||||
|
crypto.randomBytes(BUFFER_SIZE, function(err, bytes) {
|
||||||
|
self.bytesBuffer = bytes;
|
||||||
|
self.bytesBufferIndex = 0;
|
||||||
|
self.isGeneratingBytes = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to sync call when no buffered bytes are available
|
||||||
|
if (this.bytesBufferIndex == -1) {
|
||||||
|
return crypto.randomBytes(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = this.bytesBuffer.slice(bytes*this.bytesBufferIndex, bytes*(this.bytesBufferIndex+1));
|
||||||
|
this.bytesBufferIndex++;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a base64 id
|
||||||
|
*
|
||||||
|
* (Original version from socket.io <http://socket.io>)
|
||||||
|
*/
|
||||||
|
|
||||||
|
Base64Id.prototype.generateId = function () {
|
||||||
|
var rand = Buffer.alloc(15); // multiple of 3 for base64
|
||||||
|
if (!rand.writeInt32BE) {
|
||||||
|
return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString()
|
||||||
|
+ Math.abs(Math.random() * Math.random() * Date.now() | 0).toString();
|
||||||
|
}
|
||||||
|
this.sequenceNumber = (this.sequenceNumber + 1) | 0;
|
||||||
|
rand.writeInt32BE(this.sequenceNumber, 11);
|
||||||
|
if (crypto.randomBytes) {
|
||||||
|
this.getRandomBytes(12).copy(rand);
|
||||||
|
} else {
|
||||||
|
// not secure for node 0.4
|
||||||
|
[0, 4, 8].forEach(function(i) {
|
||||||
|
rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports = module.exports = new Base64Id();
|
||||||
13
node_modules/base64id/package.json
generated
vendored
Normal file
13
node_modules/base64id/package.json
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "base64id"
|
||||||
|
, "version": "2.0.0"
|
||||||
|
, "license": "MIT"
|
||||||
|
, "description": "Generates a base64 id"
|
||||||
|
, "author": "Kristian Faeldt <faeldt_kristian@cyberagent.co.jp>"
|
||||||
|
, "repository": {
|
||||||
|
"type": "git"
|
||||||
|
, "url": "https://github.com/faeldt/base64id.git"
|
||||||
|
}
|
||||||
|
, "main": "./lib/base64id.js"
|
||||||
|
, "engines": { "node": "^4.5.0 || >= 5.9" }
|
||||||
|
}
|
||||||
22
node_modules/cors/LICENSE
generated
vendored
Normal file
22
node_modules/cors/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2013 Troy Goode <troygoode@gmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
277
node_modules/cors/README.md
generated
vendored
Normal file
277
node_modules/cors/README.md
generated
vendored
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
# cors
|
||||||
|
|
||||||
|
[![NPM Version][npm-image]][npm-url]
|
||||||
|
[![NPM Downloads][downloads-image]][downloads-url]
|
||||||
|
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
|
CORS is a [Node.js](https://nodejs.org/en/) middleware for [Express](https://expressjs.com/)/[Connect](https://github.com/senchalabs/connect) that sets [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) response headers. These headers tell browsers which origins can read responses from your server.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> **How CORS Works:** This package sets response headers—it doesn't block requests. CORS is enforced by browsers: they check the headers and decide if JavaScript can read the response. Non-browser clients (curl, Postman, other servers) ignore CORS entirely. See the [MDN CORS guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) for details.
|
||||||
|
|
||||||
|
* [Installation](#installation)
|
||||||
|
* [Usage](#usage)
|
||||||
|
* [Simple Usage](#simple-usage-enable-all-cors-requests)
|
||||||
|
* [Enable CORS for a Single Route](#enable-cors-for-a-single-route)
|
||||||
|
* [Configuring CORS](#configuring-cors)
|
||||||
|
* [Configuring CORS w/ Dynamic Origin](#configuring-cors-w-dynamic-origin)
|
||||||
|
* [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)
|
||||||
|
* [Customizing CORS Settings Dynamically per Request](#customizing-cors-settings-dynamically-per-request)
|
||||||
|
* [Configuration Options](#configuration-options)
|
||||||
|
* [Common Misconceptions](#common-misconceptions)
|
||||||
|
* [License](#license)
|
||||||
|
* [Original Author](#original-author)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||||
|
[`npm install` command](https://docs.npmjs.com/downloading-and-installing-packages-locally):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install cors
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Simple Usage (Enable *All* CORS Requests)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
// Adds headers: Access-Control-Allow-Origin: *
|
||||||
|
app.use(cors())
|
||||||
|
|
||||||
|
app.get('/products/:id', function (req, res, next) {
|
||||||
|
res.json({msg: 'Hello'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enable CORS for a Single Route
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
// Adds headers: Access-Control-Allow-Origin: *
|
||||||
|
app.get('/products/:id', cors(), function (req, res, next) {
|
||||||
|
res.json({msg: 'Hello'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuring CORS
|
||||||
|
|
||||||
|
See the [configuration options](#configuration-options) for details.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
var corsOptions = {
|
||||||
|
origin: 'http://example.com',
|
||||||
|
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds headers: Access-Control-Allow-Origin: http://example.com, Vary: Origin
|
||||||
|
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
|
||||||
|
res.json({msg: 'Hello'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuring CORS w/ Dynamic Origin
|
||||||
|
|
||||||
|
This module supports validating the origin dynamically using a function provided
|
||||||
|
to the `origin` option. This function will be passed a string that is the origin
|
||||||
|
(or `undefined` if the request has no origin), and a `callback` with the signature
|
||||||
|
`callback(error, origin)`.
|
||||||
|
|
||||||
|
The `origin` argument to the callback can be any value allowed for the `origin`
|
||||||
|
option of the middleware, except a function. See the
|
||||||
|
[configuration options](#configuration-options) section for more information on all
|
||||||
|
the possible value types.
|
||||||
|
|
||||||
|
This function is designed to allow the dynamic loading of allowed origin(s) from
|
||||||
|
a backing datasource, like a database.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
var corsOptions = {
|
||||||
|
origin: function (origin, callback) {
|
||||||
|
// db.loadOrigins is an example call to load
|
||||||
|
// a list of origins from a backing database
|
||||||
|
db.loadOrigins(function (error, origins) {
|
||||||
|
callback(error, origins)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds headers: Access-Control-Allow-Origin: <matched origin>, Vary: Origin
|
||||||
|
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
|
||||||
|
res.json({msg: 'Hello'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enabling CORS Pre-Flight
|
||||||
|
|
||||||
|
Certain CORS requests are considered 'complex' and require an initial
|
||||||
|
`OPTIONS` request (called the "pre-flight request"). An example of a
|
||||||
|
'complex' CORS request is one that uses an HTTP verb other than
|
||||||
|
GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable
|
||||||
|
pre-flighting, you must add a new OPTIONS handler for the route you want
|
||||||
|
to support:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var express = require('express')
|
||||||
|
var cors = require('cors')
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
app.options('/products/:id', cors()) // preflight for DELETE
|
||||||
|
app.del('/products/:id', cors(), function (req, res, next) {
|
||||||
|
res.json({msg: 'Hello'})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also enable pre-flight across-the-board like so:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
app.options('*', cors()) // include before other routes
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: When using this middleware as an application level middleware (for
|
||||||
|
example, `app.use(cors())`), pre-flight requests are already handled for all
|
||||||
|
routes.
|
||||||
|
|
||||||
|
### Customizing CORS Settings Dynamically per Request
|
||||||
|
|
||||||
|
For APIs that require different CORS configurations for specific routes or requests, you can dynamically generate CORS options based on the incoming request. The `cors` middleware allows you to achieve this by passing a function instead of static options. This function is called for each incoming request and must use the callback pattern to return the appropriate CORS options.
|
||||||
|
|
||||||
|
The function accepts:
|
||||||
|
1. **`req`**:
|
||||||
|
- The incoming request object.
|
||||||
|
|
||||||
|
2. **`callback(error, corsOptions)`**:
|
||||||
|
- A function used to return the computed CORS options.
|
||||||
|
- **Arguments**:
|
||||||
|
- **`error`**: Pass `null` if there’s no error, or an error object to indicate a failure.
|
||||||
|
- **`corsOptions`**: An object specifying the CORS policy for the current request.
|
||||||
|
|
||||||
|
Here’s an example that handles both public routes and restricted, credential-sensitive routes:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var dynamicCorsOptions = function(req, callback) {
|
||||||
|
var corsOptions;
|
||||||
|
if (req.path.startsWith('/auth/connect/')) {
|
||||||
|
// Access-Control-Allow-Origin: http://mydomain.com, Access-Control-Allow-Credentials: true, Vary: Origin
|
||||||
|
corsOptions = {
|
||||||
|
origin: 'http://mydomain.com',
|
||||||
|
credentials: true
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Access-Control-Allow-Origin: *
|
||||||
|
corsOptions = { origin: '*' };
|
||||||
|
}
|
||||||
|
callback(null, corsOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
app.use(cors(dynamicCorsOptions));
|
||||||
|
|
||||||
|
app.get('/auth/connect/twitter', function (req, res) {
|
||||||
|
res.send('Hello');
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/public', function (req, res) {
|
||||||
|
res.send('Hello');
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(80, function () {
|
||||||
|
console.log('web server listening on port 80')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
* `origin`: Configures the **Access-Control-Allow-Origin** CORS header. Possible values:
|
||||||
|
- `Boolean` - set `origin` to `true` to reflect the [request origin](https://datatracker.ietf.org/doc/html/draft-abarth-origin-09), as defined by `req.header('Origin')`, or set it to `false` to disable CORS.
|
||||||
|
- `String` - set `origin` to a specific origin. For example, if you set it to
|
||||||
|
- `"http://example.com"` only requests from "http://example.com" will be allowed.
|
||||||
|
- `"*"` for all domains to be allowed.
|
||||||
|
- `RegExp` - set `origin` to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern `/example\.com$/` will reflect any request that is coming from an origin ending with "example.com".
|
||||||
|
- `Array` - set `origin` to an array of valid origins. Each origin can be a `String` or a `RegExp`. For example `["http://example1.com", /\.example2\.com$/]` will accept any request from "http://example1.com" or from a subdomain of "example2.com".
|
||||||
|
- `Function` - set `origin` to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (called as `callback(err, origin)`, where `origin` is a non-function value of the `origin` option) as the second.
|
||||||
|
* `methods`: Configures the **Access-Control-Allow-Methods** CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: `['GET', 'PUT', 'POST']`).
|
||||||
|
* `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Type,Authorization') or an array (ex: `['Content-Type', 'Authorization']`). If not specified, defaults to reflecting the headers specified in the request's **Access-Control-Request-Headers** header.
|
||||||
|
* `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Range,X-Content-Range') or an array (ex: `['Content-Range', 'X-Content-Range']`). If not specified, no custom headers are exposed.
|
||||||
|
* `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. Set to `true` to pass the header, otherwise it is omitted.
|
||||||
|
* `maxAge`: Configures the **Access-Control-Max-Age** CORS header. Set to an integer to pass the header, otherwise it is omitted.
|
||||||
|
* `preflightContinue`: Pass the CORS preflight response to the next handler.
|
||||||
|
* `optionsSuccessStatus`: Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`.
|
||||||
|
|
||||||
|
The default configuration is the equivalent of:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"origin": "*",
|
||||||
|
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
|
||||||
|
"preflightContinue": false,
|
||||||
|
"optionsSuccessStatus": 204
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Misconceptions
|
||||||
|
|
||||||
|
### "CORS blocks requests from disallowed origins"
|
||||||
|
|
||||||
|
**No.** Your server receives and processes every request. CORS headers tell the browser whether JavaScript can read the response—not whether the request is allowed.
|
||||||
|
|
||||||
|
### "CORS protects my API from unauthorized access"
|
||||||
|
|
||||||
|
**No.** CORS is not access control. Any HTTP client (curl, Postman, another server) can call your API regardless of CORS settings. Use authentication and authorization to protect your API.
|
||||||
|
|
||||||
|
### "Setting `origin: 'http://example.com'` means only that domain can access my server"
|
||||||
|
|
||||||
|
**No.** It means browsers will only let JavaScript from that origin read responses. The server still responds to all requests.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||||
|
|
||||||
|
## Original Author
|
||||||
|
|
||||||
|
[Troy Goode](https://github.com/TroyGoode) ([troygoode@gmail.com](mailto:troygoode@gmail.com))
|
||||||
|
|
||||||
|
[coveralls-image]: https://img.shields.io/coveralls/expressjs/cors/master.svg
|
||||||
|
[coveralls-url]: https://coveralls.io/r/expressjs/cors?branch=master
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/cors.svg
|
||||||
|
[downloads-url]: https://npmjs.com/package/cors
|
||||||
|
[github-actions-ci-image]: https://img.shields.io/github/actions/workflow/status/expressjs/cors/ci.yml?branch=master&label=ci
|
||||||
|
[github-actions-ci-url]: https://github.com/expressjs/cors?query=workflow%3Aci
|
||||||
|
[npm-image]: https://img.shields.io/npm/v/cors.svg
|
||||||
|
[npm-url]: https://npmjs.com/package/cors
|
||||||
238
node_modules/cors/lib/index.js
generated
vendored
Normal file
238
node_modules/cors/lib/index.js
generated
vendored
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
(function () {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var assign = require('object-assign');
|
||||||
|
var vary = require('vary');
|
||||||
|
|
||||||
|
var defaults = {
|
||||||
|
origin: '*',
|
||||||
|
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||||
|
preflightContinue: false,
|
||||||
|
optionsSuccessStatus: 204
|
||||||
|
};
|
||||||
|
|
||||||
|
function isString(s) {
|
||||||
|
return typeof s === 'string' || s instanceof String;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isOriginAllowed(origin, allowedOrigin) {
|
||||||
|
if (Array.isArray(allowedOrigin)) {
|
||||||
|
for (var i = 0; i < allowedOrigin.length; ++i) {
|
||||||
|
if (isOriginAllowed(origin, allowedOrigin[i])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else if (isString(allowedOrigin)) {
|
||||||
|
return origin === allowedOrigin;
|
||||||
|
} else if (allowedOrigin instanceof RegExp) {
|
||||||
|
return allowedOrigin.test(origin);
|
||||||
|
} else {
|
||||||
|
return !!allowedOrigin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureOrigin(options, req) {
|
||||||
|
var requestOrigin = req.headers.origin,
|
||||||
|
headers = [],
|
||||||
|
isAllowed;
|
||||||
|
|
||||||
|
if (!options.origin || options.origin === '*') {
|
||||||
|
// allow any origin
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Origin',
|
||||||
|
value: '*'
|
||||||
|
}]);
|
||||||
|
} else if (isString(options.origin)) {
|
||||||
|
// fixed origin
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Origin',
|
||||||
|
value: options.origin
|
||||||
|
}]);
|
||||||
|
headers.push([{
|
||||||
|
key: 'Vary',
|
||||||
|
value: 'Origin'
|
||||||
|
}]);
|
||||||
|
} else {
|
||||||
|
isAllowed = isOriginAllowed(requestOrigin, options.origin);
|
||||||
|
// reflect origin
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Origin',
|
||||||
|
value: isAllowed ? requestOrigin : false
|
||||||
|
}]);
|
||||||
|
headers.push([{
|
||||||
|
key: 'Vary',
|
||||||
|
value: 'Origin'
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureMethods(options) {
|
||||||
|
var methods = options.methods;
|
||||||
|
if (methods.join) {
|
||||||
|
methods = options.methods.join(','); // .methods is an array, so turn it into a string
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Allow-Methods',
|
||||||
|
value: methods
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureCredentials(options) {
|
||||||
|
if (options.credentials === true) {
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Allow-Credentials',
|
||||||
|
value: 'true'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureAllowedHeaders(options, req) {
|
||||||
|
var allowedHeaders = options.allowedHeaders || options.headers;
|
||||||
|
var headers = [];
|
||||||
|
|
||||||
|
if (!allowedHeaders) {
|
||||||
|
allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
|
||||||
|
headers.push([{
|
||||||
|
key: 'Vary',
|
||||||
|
value: 'Access-Control-Request-Headers'
|
||||||
|
}]);
|
||||||
|
} else if (allowedHeaders.join) {
|
||||||
|
allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string
|
||||||
|
}
|
||||||
|
if (allowedHeaders && allowedHeaders.length) {
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Headers',
|
||||||
|
value: allowedHeaders
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureExposedHeaders(options) {
|
||||||
|
var headers = options.exposedHeaders;
|
||||||
|
if (!headers) {
|
||||||
|
return null;
|
||||||
|
} else if (headers.join) {
|
||||||
|
headers = headers.join(','); // .headers is an array, so turn it into a string
|
||||||
|
}
|
||||||
|
if (headers && headers.length) {
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Expose-Headers',
|
||||||
|
value: headers
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureMaxAge(options) {
|
||||||
|
var maxAge = (typeof options.maxAge === 'number' || options.maxAge) && options.maxAge.toString()
|
||||||
|
if (maxAge && maxAge.length) {
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Max-Age',
|
||||||
|
value: maxAge
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyHeaders(headers, res) {
|
||||||
|
for (var i = 0, n = headers.length; i < n; i++) {
|
||||||
|
var header = headers[i];
|
||||||
|
if (header) {
|
||||||
|
if (Array.isArray(header)) {
|
||||||
|
applyHeaders(header, res);
|
||||||
|
} else if (header.key === 'Vary' && header.value) {
|
||||||
|
vary(res, header.value);
|
||||||
|
} else if (header.value) {
|
||||||
|
res.setHeader(header.key, header.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cors(options, req, res, next) {
|
||||||
|
var headers = [],
|
||||||
|
method = req.method && req.method.toUpperCase && req.method.toUpperCase();
|
||||||
|
|
||||||
|
if (method === 'OPTIONS') {
|
||||||
|
// preflight
|
||||||
|
headers.push(configureOrigin(options, req));
|
||||||
|
headers.push(configureCredentials(options))
|
||||||
|
headers.push(configureMethods(options))
|
||||||
|
headers.push(configureAllowedHeaders(options, req));
|
||||||
|
headers.push(configureMaxAge(options))
|
||||||
|
headers.push(configureExposedHeaders(options))
|
||||||
|
applyHeaders(headers, res);
|
||||||
|
|
||||||
|
if (options.preflightContinue) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
// Safari (and potentially other browsers) need content-length 0,
|
||||||
|
// for 204 or they just hang waiting for a body
|
||||||
|
res.statusCode = options.optionsSuccessStatus;
|
||||||
|
res.setHeader('Content-Length', '0');
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// actual response
|
||||||
|
headers.push(configureOrigin(options, req));
|
||||||
|
headers.push(configureCredentials(options))
|
||||||
|
headers.push(configureExposedHeaders(options))
|
||||||
|
applyHeaders(headers, res);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function middlewareWrapper(o) {
|
||||||
|
// if options are static (either via defaults or custom options passed in), wrap in a function
|
||||||
|
var optionsCallback = null;
|
||||||
|
if (typeof o === 'function') {
|
||||||
|
optionsCallback = o;
|
||||||
|
} else {
|
||||||
|
optionsCallback = function (req, cb) {
|
||||||
|
cb(null, o);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return function corsMiddleware(req, res, next) {
|
||||||
|
optionsCallback(req, function (err, options) {
|
||||||
|
if (err) {
|
||||||
|
next(err);
|
||||||
|
} else {
|
||||||
|
var corsOptions = assign({}, defaults, options);
|
||||||
|
var originCallback = null;
|
||||||
|
if (corsOptions.origin && typeof corsOptions.origin === 'function') {
|
||||||
|
originCallback = corsOptions.origin;
|
||||||
|
} else if (corsOptions.origin) {
|
||||||
|
originCallback = function (origin, cb) {
|
||||||
|
cb(null, corsOptions.origin);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originCallback) {
|
||||||
|
originCallback(req.headers.origin, function (err2, origin) {
|
||||||
|
if (err2 || !origin) {
|
||||||
|
next(err2);
|
||||||
|
} else {
|
||||||
|
corsOptions.origin = origin;
|
||||||
|
cors(corsOptions, req, res, next);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// can pass either an options hash, an options delegate, or nothing
|
||||||
|
module.exports = middlewareWrapper;
|
||||||
|
|
||||||
|
}());
|
||||||
42
node_modules/cors/package.json
generated
vendored
Normal file
42
node_modules/cors/package.json
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "cors",
|
||||||
|
"description": "Node.js CORS middleware",
|
||||||
|
"version": "2.8.6",
|
||||||
|
"author": "Troy Goode <troygoode@gmail.com> (https://github.com/troygoode/)",
|
||||||
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"cors",
|
||||||
|
"express",
|
||||||
|
"connect",
|
||||||
|
"middleware"
|
||||||
|
],
|
||||||
|
"repository": "expressjs/cors",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
},
|
||||||
|
"main": "./lib/index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"object-assign": "^4",
|
||||||
|
"vary": "^1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"after": "0.8.2",
|
||||||
|
"eslint": "7.30.0",
|
||||||
|
"express": "4.21.2",
|
||||||
|
"mocha": "9.2.2",
|
||||||
|
"nyc": "15.1.0",
|
||||||
|
"supertest": "6.1.3"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib/index.js"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "npm run lint && npm run test-ci",
|
||||||
|
"test-ci": "nyc --reporter=lcov --reporter=text mocha --require test/support/env",
|
||||||
|
"lint": "eslint lib test"
|
||||||
|
}
|
||||||
|
}
|
||||||
22
node_modules/engine.io-parser/LICENSE
generated
vendored
Normal file
22
node_modules/engine.io-parser/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014-present Guillermo Rauch and Socket.IO contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
158
node_modules/engine.io-parser/Readme.md
generated
vendored
Normal file
158
node_modules/engine.io-parser/Readme.md
generated
vendored
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
|
||||||
|
# engine.io-parser
|
||||||
|
|
||||||
|
[](https://github.com/socketio/engine.io-parser/actions)
|
||||||
|
[](https://npmjs.com/package/engine.io-parser)
|
||||||
|
|
||||||
|
This is the JavaScript parser for the engine.io protocol encoding,
|
||||||
|
shared by both
|
||||||
|
[engine.io-client](https://github.com/socketio/engine.io-client) and
|
||||||
|
[engine.io](https://github.com/socketio/engine.io).
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
### Standalone
|
||||||
|
|
||||||
|
The parser can encode/decode packets, payloads, and payloads as binary
|
||||||
|
with the following methods: `encodePacket`, `decodePacket`, `encodePayload`,
|
||||||
|
`decodePayload`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const parser = require("engine.io-parser");
|
||||||
|
const data = Buffer.from([ 1, 2, 3, 4 ]);
|
||||||
|
|
||||||
|
parser.encodePacket({ type: "message", data }, encoded => {
|
||||||
|
const decodedData = parser.decodePacket(encoded); // decodedData === data
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### With browserify
|
||||||
|
|
||||||
|
Engine.IO Parser is a commonjs module, which means you can include it by using
|
||||||
|
`require` on the browser and package using [browserify](http://browserify.org/):
|
||||||
|
|
||||||
|
1. install the parser package
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install engine.io-parser
|
||||||
|
```
|
||||||
|
|
||||||
|
1. write your app code
|
||||||
|
|
||||||
|
```js
|
||||||
|
const parser = require("engine.io-parser");
|
||||||
|
|
||||||
|
const testBuffer = new Int8Array(10);
|
||||||
|
for (let i = 0; i < testBuffer.length; i++) testBuffer[i] = i;
|
||||||
|
|
||||||
|
const packets = [{ type: "message", data: testBuffer.buffer }, { type: "message", data: "hello" }];
|
||||||
|
|
||||||
|
parser.encodePayload(packets, encoded => {
|
||||||
|
parser.decodePayload(encoded,
|
||||||
|
(packet, index, total) => {
|
||||||
|
const isLast = index + 1 == total;
|
||||||
|
if (!isLast) {
|
||||||
|
const buffer = new Int8Array(packet.data); // testBuffer
|
||||||
|
} else {
|
||||||
|
const message = packet.data; // "hello"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
1. build your app bundle
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ browserify app.js > bundle.js
|
||||||
|
```
|
||||||
|
|
||||||
|
1. include on your page
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="/path/to/bundle.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Runs on browser and node.js seamlessly
|
||||||
|
- Runs inside HTML5 WebWorker
|
||||||
|
- Can encode and decode packets
|
||||||
|
- Encodes from/to ArrayBuffer or Blob when in browser, and Buffer or ArrayBuffer in Node
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
Note: `cb(type)` means the type is a callback function that contains a parameter of type `type` when called.
|
||||||
|
|
||||||
|
### Node
|
||||||
|
|
||||||
|
- `encodePacket`
|
||||||
|
- Encodes a packet.
|
||||||
|
- **Parameters**
|
||||||
|
- `Object`: the packet to encode, has `type` and `data`.
|
||||||
|
- `data`: can be a `String`, `Number`, `Buffer`, `ArrayBuffer`
|
||||||
|
- `Boolean`: binary support
|
||||||
|
- `Function`: callback, returns the encoded packet (`cb(String)`)
|
||||||
|
- `decodePacket`
|
||||||
|
- Decodes a packet. Data also available as an ArrayBuffer if requested.
|
||||||
|
- Returns data as `String` or (`Blob` on browser, `ArrayBuffer` on Node)
|
||||||
|
- **Parameters**
|
||||||
|
- `String` | `ArrayBuffer`: the packet to decode, has `type` and `data`
|
||||||
|
- `String`: optional, the binary type
|
||||||
|
|
||||||
|
- `encodePayload`
|
||||||
|
- Encodes multiple messages (payload).
|
||||||
|
- If any contents are binary, they will be encoded as base64 strings. Base64
|
||||||
|
encoded strings are marked with a b before the length specifier
|
||||||
|
- **Parameters**
|
||||||
|
- `Array`: an array of packets
|
||||||
|
- `Function`: callback, returns the encoded payload (`cb(String)`)
|
||||||
|
- `decodePayload`
|
||||||
|
- Decodes data when a payload is maybe expected. Possible binary contents are
|
||||||
|
decoded from their base64 representation.
|
||||||
|
- **Parameters**
|
||||||
|
- `String`: the payload
|
||||||
|
- `Function`: callback, returns (cb(`Object`: packet, `Number`:packet index, `Number`:packet total))
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Standalone tests can be run with `npm test` which will run the node.js tests.
|
||||||
|
|
||||||
|
Browser tests are run using [zuul](https://github.com/defunctzombie/zuul).
|
||||||
|
(You must have zuul setup with a saucelabs account.)
|
||||||
|
|
||||||
|
You can run the tests locally using the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run test:browser
|
||||||
|
```
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
The support channels for `engine.io-parser` are the same as `socket.io`:
|
||||||
|
- irc.freenode.net **#socket.io**
|
||||||
|
- [Github Discussions](https://github.com/socketio/socket.io/discussions)
|
||||||
|
- [Website](https://socket.io)
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
To contribute patches, run tests or benchmarks, make sure to clone the
|
||||||
|
repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone git://github.com/socketio/engine.io-parser.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Then:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd engine.io-parser
|
||||||
|
npm ci
|
||||||
|
```
|
||||||
|
|
||||||
|
See the `Tests` section above for how to run tests before submitting any patches.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
14
node_modules/engine.io-parser/build/cjs/commons.d.ts
generated
vendored
Normal file
14
node_modules/engine.io-parser/build/cjs/commons.d.ts
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
declare const PACKET_TYPES: any;
|
||||||
|
declare const PACKET_TYPES_REVERSE: any;
|
||||||
|
declare const ERROR_PACKET: Packet;
|
||||||
|
export { PACKET_TYPES, PACKET_TYPES_REVERSE, ERROR_PACKET };
|
||||||
|
export type PacketType = "open" | "close" | "ping" | "pong" | "message" | "upgrade" | "noop" | "error";
|
||||||
|
export type RawData = any;
|
||||||
|
export interface Packet {
|
||||||
|
type: PacketType;
|
||||||
|
options?: {
|
||||||
|
compress: boolean;
|
||||||
|
};
|
||||||
|
data?: RawData;
|
||||||
|
}
|
||||||
|
export type BinaryType = "nodebuffer" | "arraybuffer" | "blob";
|
||||||
19
node_modules/engine.io-parser/build/cjs/commons.js
generated
vendored
Normal file
19
node_modules/engine.io-parser/build/cjs/commons.js
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.ERROR_PACKET = exports.PACKET_TYPES_REVERSE = exports.PACKET_TYPES = void 0;
|
||||||
|
const PACKET_TYPES = Object.create(null); // no Map = no polyfill
|
||||||
|
exports.PACKET_TYPES = PACKET_TYPES;
|
||||||
|
PACKET_TYPES["open"] = "0";
|
||||||
|
PACKET_TYPES["close"] = "1";
|
||||||
|
PACKET_TYPES["ping"] = "2";
|
||||||
|
PACKET_TYPES["pong"] = "3";
|
||||||
|
PACKET_TYPES["message"] = "4";
|
||||||
|
PACKET_TYPES["upgrade"] = "5";
|
||||||
|
PACKET_TYPES["noop"] = "6";
|
||||||
|
const PACKET_TYPES_REVERSE = Object.create(null);
|
||||||
|
exports.PACKET_TYPES_REVERSE = PACKET_TYPES_REVERSE;
|
||||||
|
Object.keys(PACKET_TYPES).forEach((key) => {
|
||||||
|
PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
|
||||||
|
});
|
||||||
|
const ERROR_PACKET = { type: "error", data: "parser error" };
|
||||||
|
exports.ERROR_PACKET = ERROR_PACKET;
|
||||||
2
node_modules/engine.io-parser/build/cjs/contrib/base64-arraybuffer.d.ts
generated
vendored
Normal file
2
node_modules/engine.io-parser/build/cjs/contrib/base64-arraybuffer.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export declare const encode: (arraybuffer: ArrayBuffer) => string;
|
||||||
|
export declare const decode: (base64: string) => ArrayBuffer;
|
||||||
48
node_modules/engine.io-parser/build/cjs/contrib/base64-arraybuffer.js
generated
vendored
Normal file
48
node_modules/engine.io-parser/build/cjs/contrib/base64-arraybuffer.js
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.decode = exports.encode = void 0;
|
||||||
|
// imported from https://github.com/socketio/base64-arraybuffer
|
||||||
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
|
// Use a lookup table to find the index.
|
||||||
|
const lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
|
||||||
|
for (let i = 0; i < chars.length; i++) {
|
||||||
|
lookup[chars.charCodeAt(i)] = i;
|
||||||
|
}
|
||||||
|
const encode = (arraybuffer) => {
|
||||||
|
let bytes = new Uint8Array(arraybuffer), i, len = bytes.length, base64 = '';
|
||||||
|
for (i = 0; i < len; i += 3) {
|
||||||
|
base64 += chars[bytes[i] >> 2];
|
||||||
|
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
|
||||||
|
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
|
||||||
|
base64 += chars[bytes[i + 2] & 63];
|
||||||
|
}
|
||||||
|
if (len % 3 === 2) {
|
||||||
|
base64 = base64.substring(0, base64.length - 1) + '=';
|
||||||
|
}
|
||||||
|
else if (len % 3 === 1) {
|
||||||
|
base64 = base64.substring(0, base64.length - 2) + '==';
|
||||||
|
}
|
||||||
|
return base64;
|
||||||
|
};
|
||||||
|
exports.encode = encode;
|
||||||
|
const decode = (base64) => {
|
||||||
|
let bufferLength = base64.length * 0.75, len = base64.length, i, p = 0, encoded1, encoded2, encoded3, encoded4;
|
||||||
|
if (base64[base64.length - 1] === '=') {
|
||||||
|
bufferLength--;
|
||||||
|
if (base64[base64.length - 2] === '=') {
|
||||||
|
bufferLength--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const arraybuffer = new ArrayBuffer(bufferLength), bytes = new Uint8Array(arraybuffer);
|
||||||
|
for (i = 0; i < len; i += 4) {
|
||||||
|
encoded1 = lookup[base64.charCodeAt(i)];
|
||||||
|
encoded2 = lookup[base64.charCodeAt(i + 1)];
|
||||||
|
encoded3 = lookup[base64.charCodeAt(i + 2)];
|
||||||
|
encoded4 = lookup[base64.charCodeAt(i + 3)];
|
||||||
|
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
||||||
|
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
||||||
|
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
|
||||||
|
}
|
||||||
|
return arraybuffer;
|
||||||
|
};
|
||||||
|
exports.decode = decode;
|
||||||
2
node_modules/engine.io-parser/build/cjs/decodePacket.browser.d.ts
generated
vendored
Normal file
2
node_modules/engine.io-parser/build/cjs/decodePacket.browser.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import { Packet, BinaryType, RawData } from "./commons.js";
|
||||||
|
export declare const decodePacket: (encodedPacket: RawData, binaryType?: BinaryType) => Packet;
|
||||||
66
node_modules/engine.io-parser/build/cjs/decodePacket.browser.js
generated
vendored
Normal file
66
node_modules/engine.io-parser/build/cjs/decodePacket.browser.js
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.decodePacket = void 0;
|
||||||
|
const commons_js_1 = require("./commons.js");
|
||||||
|
const base64_arraybuffer_js_1 = require("./contrib/base64-arraybuffer.js");
|
||||||
|
const withNativeArrayBuffer = typeof ArrayBuffer === "function";
|
||||||
|
const decodePacket = (encodedPacket, binaryType) => {
|
||||||
|
if (typeof encodedPacket !== "string") {
|
||||||
|
return {
|
||||||
|
type: "message",
|
||||||
|
data: mapBinary(encodedPacket, binaryType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const type = encodedPacket.charAt(0);
|
||||||
|
if (type === "b") {
|
||||||
|
return {
|
||||||
|
type: "message",
|
||||||
|
data: decodeBase64Packet(encodedPacket.substring(1), binaryType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const packetType = commons_js_1.PACKET_TYPES_REVERSE[type];
|
||||||
|
if (!packetType) {
|
||||||
|
return commons_js_1.ERROR_PACKET;
|
||||||
|
}
|
||||||
|
return encodedPacket.length > 1
|
||||||
|
? {
|
||||||
|
type: commons_js_1.PACKET_TYPES_REVERSE[type],
|
||||||
|
data: encodedPacket.substring(1),
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: commons_js_1.PACKET_TYPES_REVERSE[type],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
exports.decodePacket = decodePacket;
|
||||||
|
const decodeBase64Packet = (data, binaryType) => {
|
||||||
|
if (withNativeArrayBuffer) {
|
||||||
|
const decoded = (0, base64_arraybuffer_js_1.decode)(data);
|
||||||
|
return mapBinary(decoded, binaryType);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { base64: true, data }; // fallback for old browsers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const mapBinary = (data, binaryType) => {
|
||||||
|
switch (binaryType) {
|
||||||
|
case "blob":
|
||||||
|
if (data instanceof Blob) {
|
||||||
|
// from WebSocket + binaryType "blob"
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// from HTTP long-polling or WebTransport
|
||||||
|
return new Blob([data]);
|
||||||
|
}
|
||||||
|
case "arraybuffer":
|
||||||
|
default:
|
||||||
|
if (data instanceof ArrayBuffer) {
|
||||||
|
// from HTTP long-polling (base64) or WebSocket + binaryType "arraybuffer"
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// from WebTransport (Uint8Array)
|
||||||
|
return data.buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
2
node_modules/engine.io-parser/build/cjs/decodePacket.d.ts
generated
vendored
Normal file
2
node_modules/engine.io-parser/build/cjs/decodePacket.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import { Packet, BinaryType, RawData } from "./commons.js";
|
||||||
|
export declare const decodePacket: (encodedPacket: RawData, binaryType?: BinaryType) => Packet;
|
||||||
59
node_modules/engine.io-parser/build/cjs/decodePacket.js
generated
vendored
Normal file
59
node_modules/engine.io-parser/build/cjs/decodePacket.js
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.decodePacket = void 0;
|
||||||
|
const commons_js_1 = require("./commons.js");
|
||||||
|
const decodePacket = (encodedPacket, binaryType) => {
|
||||||
|
if (typeof encodedPacket !== "string") {
|
||||||
|
return {
|
||||||
|
type: "message",
|
||||||
|
data: mapBinary(encodedPacket, binaryType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const type = encodedPacket.charAt(0);
|
||||||
|
if (type === "b") {
|
||||||
|
const buffer = Buffer.from(encodedPacket.substring(1), "base64");
|
||||||
|
return {
|
||||||
|
type: "message",
|
||||||
|
data: mapBinary(buffer, binaryType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!commons_js_1.PACKET_TYPES_REVERSE[type]) {
|
||||||
|
return commons_js_1.ERROR_PACKET;
|
||||||
|
}
|
||||||
|
return encodedPacket.length > 1
|
||||||
|
? {
|
||||||
|
type: commons_js_1.PACKET_TYPES_REVERSE[type],
|
||||||
|
data: encodedPacket.substring(1),
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: commons_js_1.PACKET_TYPES_REVERSE[type],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
exports.decodePacket = decodePacket;
|
||||||
|
const mapBinary = (data, binaryType) => {
|
||||||
|
switch (binaryType) {
|
||||||
|
case "arraybuffer":
|
||||||
|
if (data instanceof ArrayBuffer) {
|
||||||
|
// from WebSocket & binaryType "arraybuffer"
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else if (Buffer.isBuffer(data)) {
|
||||||
|
// from HTTP long-polling
|
||||||
|
return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// from WebTransport (Uint8Array)
|
||||||
|
return data.buffer;
|
||||||
|
}
|
||||||
|
case "nodebuffer":
|
||||||
|
default:
|
||||||
|
if (Buffer.isBuffer(data)) {
|
||||||
|
// from HTTP long-polling or WebSocket & binaryType "nodebuffer" (default)
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// from WebTransport (Uint8Array)
|
||||||
|
return Buffer.from(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
4
node_modules/engine.io-parser/build/cjs/encodePacket.browser.d.ts
generated
vendored
Normal file
4
node_modules/engine.io-parser/build/cjs/encodePacket.browser.d.ts
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { Packet, RawData } from "./commons.js";
|
||||||
|
declare const encodePacket: ({ type, data }: Packet, supportsBinary: boolean, callback: (encodedPacket: RawData) => void) => void;
|
||||||
|
export declare function encodePacketToBinary(packet: Packet, callback: (encodedPacket: RawData) => void): void | Promise<void>;
|
||||||
|
export { encodePacket };
|
||||||
72
node_modules/engine.io-parser/build/cjs/encodePacket.browser.js
generated
vendored
Normal file
72
node_modules/engine.io-parser/build/cjs/encodePacket.browser.js
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.encodePacket = void 0;
|
||||||
|
exports.encodePacketToBinary = encodePacketToBinary;
|
||||||
|
const commons_js_1 = require("./commons.js");
|
||||||
|
const withNativeBlob = typeof Blob === "function" ||
|
||||||
|
(typeof Blob !== "undefined" &&
|
||||||
|
Object.prototype.toString.call(Blob) === "[object BlobConstructor]");
|
||||||
|
const withNativeArrayBuffer = typeof ArrayBuffer === "function";
|
||||||
|
// ArrayBuffer.isView method is not defined in IE10
|
||||||
|
const isView = (obj) => {
|
||||||
|
return typeof ArrayBuffer.isView === "function"
|
||||||
|
? ArrayBuffer.isView(obj)
|
||||||
|
: obj && obj.buffer instanceof ArrayBuffer;
|
||||||
|
};
|
||||||
|
const encodePacket = ({ type, data }, supportsBinary, callback) => {
|
||||||
|
if (withNativeBlob && data instanceof Blob) {
|
||||||
|
if (supportsBinary) {
|
||||||
|
return callback(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return encodeBlobAsBase64(data, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (withNativeArrayBuffer &&
|
||||||
|
(data instanceof ArrayBuffer || isView(data))) {
|
||||||
|
if (supportsBinary) {
|
||||||
|
return callback(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return encodeBlobAsBase64(new Blob([data]), callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// plain string
|
||||||
|
return callback(commons_js_1.PACKET_TYPES[type] + (data || ""));
|
||||||
|
};
|
||||||
|
exports.encodePacket = encodePacket;
|
||||||
|
const encodeBlobAsBase64 = (data, callback) => {
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onload = function () {
|
||||||
|
const content = fileReader.result.split(",")[1];
|
||||||
|
callback("b" + (content || ""));
|
||||||
|
};
|
||||||
|
return fileReader.readAsDataURL(data);
|
||||||
|
};
|
||||||
|
function toArray(data) {
|
||||||
|
if (data instanceof Uint8Array) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else if (data instanceof ArrayBuffer) {
|
||||||
|
return new Uint8Array(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let TEXT_ENCODER;
|
||||||
|
function encodePacketToBinary(packet, callback) {
|
||||||
|
if (withNativeBlob && packet.data instanceof Blob) {
|
||||||
|
return packet.data.arrayBuffer().then(toArray).then(callback);
|
||||||
|
}
|
||||||
|
else if (withNativeArrayBuffer &&
|
||||||
|
(packet.data instanceof ArrayBuffer || isView(packet.data))) {
|
||||||
|
return callback(toArray(packet.data));
|
||||||
|
}
|
||||||
|
encodePacket(packet, false, (encoded) => {
|
||||||
|
if (!TEXT_ENCODER) {
|
||||||
|
TEXT_ENCODER = new TextEncoder();
|
||||||
|
}
|
||||||
|
callback(TEXT_ENCODER.encode(encoded));
|
||||||
|
});
|
||||||
|
}
|
||||||
3
node_modules/engine.io-parser/build/cjs/encodePacket.d.ts
generated
vendored
Normal file
3
node_modules/engine.io-parser/build/cjs/encodePacket.d.ts
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { Packet, RawData } from "./commons.js";
|
||||||
|
export declare const encodePacket: ({ type, data }: Packet, supportsBinary: boolean, callback: (encodedPacket: RawData) => void) => void;
|
||||||
|
export declare function encodePacketToBinary(packet: Packet, callback: (encodedPacket: RawData) => void): void;
|
||||||
38
node_modules/engine.io-parser/build/cjs/encodePacket.js
generated
vendored
Normal file
38
node_modules/engine.io-parser/build/cjs/encodePacket.js
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.encodePacket = void 0;
|
||||||
|
exports.encodePacketToBinary = encodePacketToBinary;
|
||||||
|
const commons_js_1 = require("./commons.js");
|
||||||
|
const encodePacket = ({ type, data }, supportsBinary, callback) => {
|
||||||
|
if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
|
||||||
|
return callback(supportsBinary ? data : "b" + toBuffer(data, true).toString("base64"));
|
||||||
|
}
|
||||||
|
// plain string
|
||||||
|
return callback(commons_js_1.PACKET_TYPES[type] + (data || ""));
|
||||||
|
};
|
||||||
|
exports.encodePacket = encodePacket;
|
||||||
|
const toBuffer = (data, forceBufferConversion) => {
|
||||||
|
if (Buffer.isBuffer(data) ||
|
||||||
|
(data instanceof Uint8Array && !forceBufferConversion)) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else if (data instanceof ArrayBuffer) {
|
||||||
|
return Buffer.from(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let TEXT_ENCODER;
|
||||||
|
function encodePacketToBinary(packet, callback) {
|
||||||
|
if (packet.data instanceof ArrayBuffer || ArrayBuffer.isView(packet.data)) {
|
||||||
|
return callback(toBuffer(packet.data, false));
|
||||||
|
}
|
||||||
|
(0, exports.encodePacket)(packet, true, (encoded) => {
|
||||||
|
if (!TEXT_ENCODER) {
|
||||||
|
// lazily created for compatibility with Node.js 10
|
||||||
|
TEXT_ENCODER = new TextEncoder();
|
||||||
|
}
|
||||||
|
callback(TEXT_ENCODER.encode(encoded));
|
||||||
|
});
|
||||||
|
}
|
||||||
9
node_modules/engine.io-parser/build/cjs/index.d.ts
generated
vendored
Normal file
9
node_modules/engine.io-parser/build/cjs/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { encodePacket } from "./encodePacket.js";
|
||||||
|
import { decodePacket } from "./decodePacket.js";
|
||||||
|
import { Packet, PacketType, RawData, BinaryType } from "./commons.js";
|
||||||
|
declare const encodePayload: (packets: Packet[], callback: (encodedPayload: string) => void) => void;
|
||||||
|
declare const decodePayload: (encodedPayload: string, binaryType?: BinaryType) => Packet[];
|
||||||
|
export declare function createPacketEncoderStream(): any;
|
||||||
|
export declare function createPacketDecoderStream(maxPayload: number, binaryType: BinaryType): any;
|
||||||
|
export declare const protocol = 4;
|
||||||
|
export { encodePacket, encodePayload, decodePacket, decodePayload, Packet, PacketType, RawData, BinaryType, };
|
||||||
164
node_modules/engine.io-parser/build/cjs/index.js
generated
vendored
Normal file
164
node_modules/engine.io-parser/build/cjs/index.js
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.decodePayload = exports.decodePacket = exports.encodePayload = exports.encodePacket = exports.protocol = void 0;
|
||||||
|
exports.createPacketEncoderStream = createPacketEncoderStream;
|
||||||
|
exports.createPacketDecoderStream = createPacketDecoderStream;
|
||||||
|
const encodePacket_js_1 = require("./encodePacket.js");
|
||||||
|
Object.defineProperty(exports, "encodePacket", { enumerable: true, get: function () { return encodePacket_js_1.encodePacket; } });
|
||||||
|
const decodePacket_js_1 = require("./decodePacket.js");
|
||||||
|
Object.defineProperty(exports, "decodePacket", { enumerable: true, get: function () { return decodePacket_js_1.decodePacket; } });
|
||||||
|
const commons_js_1 = require("./commons.js");
|
||||||
|
const SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text
|
||||||
|
const encodePayload = (packets, callback) => {
|
||||||
|
// some packets may be added to the array while encoding, so the initial length must be saved
|
||||||
|
const length = packets.length;
|
||||||
|
const encodedPackets = new Array(length);
|
||||||
|
let count = 0;
|
||||||
|
packets.forEach((packet, i) => {
|
||||||
|
// force base64 encoding for binary packets
|
||||||
|
(0, encodePacket_js_1.encodePacket)(packet, false, (encodedPacket) => {
|
||||||
|
encodedPackets[i] = encodedPacket;
|
||||||
|
if (++count === length) {
|
||||||
|
callback(encodedPackets.join(SEPARATOR));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.encodePayload = encodePayload;
|
||||||
|
const decodePayload = (encodedPayload, binaryType) => {
|
||||||
|
const encodedPackets = encodedPayload.split(SEPARATOR);
|
||||||
|
const packets = [];
|
||||||
|
for (let i = 0; i < encodedPackets.length; i++) {
|
||||||
|
const decodedPacket = (0, decodePacket_js_1.decodePacket)(encodedPackets[i], binaryType);
|
||||||
|
packets.push(decodedPacket);
|
||||||
|
if (decodedPacket.type === "error") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return packets;
|
||||||
|
};
|
||||||
|
exports.decodePayload = decodePayload;
|
||||||
|
function createPacketEncoderStream() {
|
||||||
|
return new TransformStream({
|
||||||
|
transform(packet, controller) {
|
||||||
|
(0, encodePacket_js_1.encodePacketToBinary)(packet, (encodedPacket) => {
|
||||||
|
const payloadLength = encodedPacket.length;
|
||||||
|
let header;
|
||||||
|
// inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
|
||||||
|
if (payloadLength < 126) {
|
||||||
|
header = new Uint8Array(1);
|
||||||
|
new DataView(header.buffer).setUint8(0, payloadLength);
|
||||||
|
}
|
||||||
|
else if (payloadLength < 65536) {
|
||||||
|
header = new Uint8Array(3);
|
||||||
|
const view = new DataView(header.buffer);
|
||||||
|
view.setUint8(0, 126);
|
||||||
|
view.setUint16(1, payloadLength);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
header = new Uint8Array(9);
|
||||||
|
const view = new DataView(header.buffer);
|
||||||
|
view.setUint8(0, 127);
|
||||||
|
view.setBigUint64(1, BigInt(payloadLength));
|
||||||
|
}
|
||||||
|
// first bit indicates whether the payload is plain text (0) or binary (1)
|
||||||
|
if (packet.data && typeof packet.data !== "string") {
|
||||||
|
header[0] |= 0x80;
|
||||||
|
}
|
||||||
|
controller.enqueue(header);
|
||||||
|
controller.enqueue(encodedPacket);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let TEXT_DECODER;
|
||||||
|
function totalLength(chunks) {
|
||||||
|
return chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
||||||
|
}
|
||||||
|
function concatChunks(chunks, size) {
|
||||||
|
if (chunks[0].length === size) {
|
||||||
|
return chunks.shift();
|
||||||
|
}
|
||||||
|
const buffer = new Uint8Array(size);
|
||||||
|
let j = 0;
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
buffer[i] = chunks[0][j++];
|
||||||
|
if (j === chunks[0].length) {
|
||||||
|
chunks.shift();
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chunks.length && j < chunks[0].length) {
|
||||||
|
chunks[0] = chunks[0].slice(j);
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
function createPacketDecoderStream(maxPayload, binaryType) {
|
||||||
|
if (!TEXT_DECODER) {
|
||||||
|
TEXT_DECODER = new TextDecoder();
|
||||||
|
}
|
||||||
|
const chunks = [];
|
||||||
|
let state = 0 /* State.READ_HEADER */;
|
||||||
|
let expectedLength = -1;
|
||||||
|
let isBinary = false;
|
||||||
|
return new TransformStream({
|
||||||
|
transform(chunk, controller) {
|
||||||
|
chunks.push(chunk);
|
||||||
|
while (true) {
|
||||||
|
if (state === 0 /* State.READ_HEADER */) {
|
||||||
|
if (totalLength(chunks) < 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const header = concatChunks(chunks, 1);
|
||||||
|
isBinary = (header[0] & 0x80) === 0x80;
|
||||||
|
expectedLength = header[0] & 0x7f;
|
||||||
|
if (expectedLength < 126) {
|
||||||
|
state = 3 /* State.READ_PAYLOAD */;
|
||||||
|
}
|
||||||
|
else if (expectedLength === 126) {
|
||||||
|
state = 1 /* State.READ_EXTENDED_LENGTH_16 */;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state = 2 /* State.READ_EXTENDED_LENGTH_64 */;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state === 1 /* State.READ_EXTENDED_LENGTH_16 */) {
|
||||||
|
if (totalLength(chunks) < 2) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const headerArray = concatChunks(chunks, 2);
|
||||||
|
expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);
|
||||||
|
state = 3 /* State.READ_PAYLOAD */;
|
||||||
|
}
|
||||||
|
else if (state === 2 /* State.READ_EXTENDED_LENGTH_64 */) {
|
||||||
|
if (totalLength(chunks) < 8) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const headerArray = concatChunks(chunks, 8);
|
||||||
|
const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);
|
||||||
|
const n = view.getUint32(0);
|
||||||
|
if (n > Math.pow(2, 53 - 32) - 1) {
|
||||||
|
// the maximum safe integer in JavaScript is 2^53 - 1
|
||||||
|
controller.enqueue(commons_js_1.ERROR_PACKET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
expectedLength = n * Math.pow(2, 32) + view.getUint32(4);
|
||||||
|
state = 3 /* State.READ_PAYLOAD */;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (totalLength(chunks) < expectedLength) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const data = concatChunks(chunks, expectedLength);
|
||||||
|
controller.enqueue((0, decodePacket_js_1.decodePacket)(isBinary ? data : TEXT_DECODER.decode(data), binaryType));
|
||||||
|
state = 0 /* State.READ_HEADER */;
|
||||||
|
}
|
||||||
|
if (expectedLength === 0 || expectedLength > maxPayload) {
|
||||||
|
controller.enqueue(commons_js_1.ERROR_PACKET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.protocol = 4;
|
||||||
8
node_modules/engine.io-parser/build/cjs/package.json
generated
vendored
Normal file
8
node_modules/engine.io-parser/build/cjs/package.json
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "engine.io-parser",
|
||||||
|
"type": "commonjs",
|
||||||
|
"browser": {
|
||||||
|
"./encodePacket.js": "./encodePacket.browser.js",
|
||||||
|
"./decodePacket.js": "./decodePacket.browser.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
14
node_modules/engine.io-parser/build/esm/commons.d.ts
generated
vendored
Normal file
14
node_modules/engine.io-parser/build/esm/commons.d.ts
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
declare const PACKET_TYPES: any;
|
||||||
|
declare const PACKET_TYPES_REVERSE: any;
|
||||||
|
declare const ERROR_PACKET: Packet;
|
||||||
|
export { PACKET_TYPES, PACKET_TYPES_REVERSE, ERROR_PACKET };
|
||||||
|
export type PacketType = "open" | "close" | "ping" | "pong" | "message" | "upgrade" | "noop" | "error";
|
||||||
|
export type RawData = any;
|
||||||
|
export interface Packet {
|
||||||
|
type: PacketType;
|
||||||
|
options?: {
|
||||||
|
compress: boolean;
|
||||||
|
};
|
||||||
|
data?: RawData;
|
||||||
|
}
|
||||||
|
export type BinaryType = "nodebuffer" | "arraybuffer" | "blob";
|
||||||
14
node_modules/engine.io-parser/build/esm/commons.js
generated
vendored
Normal file
14
node_modules/engine.io-parser/build/esm/commons.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const PACKET_TYPES = Object.create(null); // no Map = no polyfill
|
||||||
|
PACKET_TYPES["open"] = "0";
|
||||||
|
PACKET_TYPES["close"] = "1";
|
||||||
|
PACKET_TYPES["ping"] = "2";
|
||||||
|
PACKET_TYPES["pong"] = "3";
|
||||||
|
PACKET_TYPES["message"] = "4";
|
||||||
|
PACKET_TYPES["upgrade"] = "5";
|
||||||
|
PACKET_TYPES["noop"] = "6";
|
||||||
|
const PACKET_TYPES_REVERSE = Object.create(null);
|
||||||
|
Object.keys(PACKET_TYPES).forEach((key) => {
|
||||||
|
PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
|
||||||
|
});
|
||||||
|
const ERROR_PACKET = { type: "error", data: "parser error" };
|
||||||
|
export { PACKET_TYPES, PACKET_TYPES_REVERSE, ERROR_PACKET };
|
||||||
2
node_modules/engine.io-parser/build/esm/contrib/base64-arraybuffer.d.ts
generated
vendored
Normal file
2
node_modules/engine.io-parser/build/esm/contrib/base64-arraybuffer.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export declare const encode: (arraybuffer: ArrayBuffer) => string;
|
||||||
|
export declare const decode: (base64: string) => ArrayBuffer;
|
||||||
43
node_modules/engine.io-parser/build/esm/contrib/base64-arraybuffer.js
generated
vendored
Normal file
43
node_modules/engine.io-parser/build/esm/contrib/base64-arraybuffer.js
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// imported from https://github.com/socketio/base64-arraybuffer
|
||||||
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
|
// Use a lookup table to find the index.
|
||||||
|
const lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
|
||||||
|
for (let i = 0; i < chars.length; i++) {
|
||||||
|
lookup[chars.charCodeAt(i)] = i;
|
||||||
|
}
|
||||||
|
export const encode = (arraybuffer) => {
|
||||||
|
let bytes = new Uint8Array(arraybuffer), i, len = bytes.length, base64 = '';
|
||||||
|
for (i = 0; i < len; i += 3) {
|
||||||
|
base64 += chars[bytes[i] >> 2];
|
||||||
|
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
|
||||||
|
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
|
||||||
|
base64 += chars[bytes[i + 2] & 63];
|
||||||
|
}
|
||||||
|
if (len % 3 === 2) {
|
||||||
|
base64 = base64.substring(0, base64.length - 1) + '=';
|
||||||
|
}
|
||||||
|
else if (len % 3 === 1) {
|
||||||
|
base64 = base64.substring(0, base64.length - 2) + '==';
|
||||||
|
}
|
||||||
|
return base64;
|
||||||
|
};
|
||||||
|
export const decode = (base64) => {
|
||||||
|
let bufferLength = base64.length * 0.75, len = base64.length, i, p = 0, encoded1, encoded2, encoded3, encoded4;
|
||||||
|
if (base64[base64.length - 1] === '=') {
|
||||||
|
bufferLength--;
|
||||||
|
if (base64[base64.length - 2] === '=') {
|
||||||
|
bufferLength--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const arraybuffer = new ArrayBuffer(bufferLength), bytes = new Uint8Array(arraybuffer);
|
||||||
|
for (i = 0; i < len; i += 4) {
|
||||||
|
encoded1 = lookup[base64.charCodeAt(i)];
|
||||||
|
encoded2 = lookup[base64.charCodeAt(i + 1)];
|
||||||
|
encoded3 = lookup[base64.charCodeAt(i + 2)];
|
||||||
|
encoded4 = lookup[base64.charCodeAt(i + 3)];
|
||||||
|
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
||||||
|
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
||||||
|
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
|
||||||
|
}
|
||||||
|
return arraybuffer;
|
||||||
|
};
|
||||||
2
node_modules/engine.io-parser/build/esm/decodePacket.browser.d.ts
generated
vendored
Normal file
2
node_modules/engine.io-parser/build/esm/decodePacket.browser.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import { Packet, BinaryType, RawData } from "./commons.js";
|
||||||
|
export declare const decodePacket: (encodedPacket: RawData, binaryType?: BinaryType) => Packet;
|
||||||
62
node_modules/engine.io-parser/build/esm/decodePacket.browser.js
generated
vendored
Normal file
62
node_modules/engine.io-parser/build/esm/decodePacket.browser.js
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { ERROR_PACKET, PACKET_TYPES_REVERSE, } from "./commons.js";
|
||||||
|
import { decode } from "./contrib/base64-arraybuffer.js";
|
||||||
|
const withNativeArrayBuffer = typeof ArrayBuffer === "function";
|
||||||
|
export const decodePacket = (encodedPacket, binaryType) => {
|
||||||
|
if (typeof encodedPacket !== "string") {
|
||||||
|
return {
|
||||||
|
type: "message",
|
||||||
|
data: mapBinary(encodedPacket, binaryType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const type = encodedPacket.charAt(0);
|
||||||
|
if (type === "b") {
|
||||||
|
return {
|
||||||
|
type: "message",
|
||||||
|
data: decodeBase64Packet(encodedPacket.substring(1), binaryType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const packetType = PACKET_TYPES_REVERSE[type];
|
||||||
|
if (!packetType) {
|
||||||
|
return ERROR_PACKET;
|
||||||
|
}
|
||||||
|
return encodedPacket.length > 1
|
||||||
|
? {
|
||||||
|
type: PACKET_TYPES_REVERSE[type],
|
||||||
|
data: encodedPacket.substring(1),
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: PACKET_TYPES_REVERSE[type],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const decodeBase64Packet = (data, binaryType) => {
|
||||||
|
if (withNativeArrayBuffer) {
|
||||||
|
const decoded = decode(data);
|
||||||
|
return mapBinary(decoded, binaryType);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { base64: true, data }; // fallback for old browsers
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const mapBinary = (data, binaryType) => {
|
||||||
|
switch (binaryType) {
|
||||||
|
case "blob":
|
||||||
|
if (data instanceof Blob) {
|
||||||
|
// from WebSocket + binaryType "blob"
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// from HTTP long-polling or WebTransport
|
||||||
|
return new Blob([data]);
|
||||||
|
}
|
||||||
|
case "arraybuffer":
|
||||||
|
default:
|
||||||
|
if (data instanceof ArrayBuffer) {
|
||||||
|
// from HTTP long-polling (base64) or WebSocket + binaryType "arraybuffer"
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// from WebTransport (Uint8Array)
|
||||||
|
return data.buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
2
node_modules/engine.io-parser/build/esm/decodePacket.d.ts
generated
vendored
Normal file
2
node_modules/engine.io-parser/build/esm/decodePacket.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import { Packet, BinaryType, RawData } from "./commons.js";
|
||||||
|
export declare const decodePacket: (encodedPacket: RawData, binaryType?: BinaryType) => Packet;
|
||||||
55
node_modules/engine.io-parser/build/esm/decodePacket.js
generated
vendored
Normal file
55
node_modules/engine.io-parser/build/esm/decodePacket.js
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { ERROR_PACKET, PACKET_TYPES_REVERSE, } from "./commons.js";
|
||||||
|
export const decodePacket = (encodedPacket, binaryType) => {
|
||||||
|
if (typeof encodedPacket !== "string") {
|
||||||
|
return {
|
||||||
|
type: "message",
|
||||||
|
data: mapBinary(encodedPacket, binaryType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const type = encodedPacket.charAt(0);
|
||||||
|
if (type === "b") {
|
||||||
|
const buffer = Buffer.from(encodedPacket.substring(1), "base64");
|
||||||
|
return {
|
||||||
|
type: "message",
|
||||||
|
data: mapBinary(buffer, binaryType),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!PACKET_TYPES_REVERSE[type]) {
|
||||||
|
return ERROR_PACKET;
|
||||||
|
}
|
||||||
|
return encodedPacket.length > 1
|
||||||
|
? {
|
||||||
|
type: PACKET_TYPES_REVERSE[type],
|
||||||
|
data: encodedPacket.substring(1),
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: PACKET_TYPES_REVERSE[type],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const mapBinary = (data, binaryType) => {
|
||||||
|
switch (binaryType) {
|
||||||
|
case "arraybuffer":
|
||||||
|
if (data instanceof ArrayBuffer) {
|
||||||
|
// from WebSocket & binaryType "arraybuffer"
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else if (Buffer.isBuffer(data)) {
|
||||||
|
// from HTTP long-polling
|
||||||
|
return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// from WebTransport (Uint8Array)
|
||||||
|
return data.buffer;
|
||||||
|
}
|
||||||
|
case "nodebuffer":
|
||||||
|
default:
|
||||||
|
if (Buffer.isBuffer(data)) {
|
||||||
|
// from HTTP long-polling or WebSocket & binaryType "nodebuffer" (default)
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// from WebTransport (Uint8Array)
|
||||||
|
return Buffer.from(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
4
node_modules/engine.io-parser/build/esm/encodePacket.browser.d.ts
generated
vendored
Normal file
4
node_modules/engine.io-parser/build/esm/encodePacket.browser.d.ts
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { Packet, RawData } from "./commons.js";
|
||||||
|
declare const encodePacket: ({ type, data }: Packet, supportsBinary: boolean, callback: (encodedPacket: RawData) => void) => void;
|
||||||
|
export declare function encodePacketToBinary(packet: Packet, callback: (encodedPacket: RawData) => void): void | Promise<void>;
|
||||||
|
export { encodePacket };
|
||||||
68
node_modules/engine.io-parser/build/esm/encodePacket.browser.js
generated
vendored
Normal file
68
node_modules/engine.io-parser/build/esm/encodePacket.browser.js
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import { PACKET_TYPES } from "./commons.js";
|
||||||
|
const withNativeBlob = typeof Blob === "function" ||
|
||||||
|
(typeof Blob !== "undefined" &&
|
||||||
|
Object.prototype.toString.call(Blob) === "[object BlobConstructor]");
|
||||||
|
const withNativeArrayBuffer = typeof ArrayBuffer === "function";
|
||||||
|
// ArrayBuffer.isView method is not defined in IE10
|
||||||
|
const isView = (obj) => {
|
||||||
|
return typeof ArrayBuffer.isView === "function"
|
||||||
|
? ArrayBuffer.isView(obj)
|
||||||
|
: obj && obj.buffer instanceof ArrayBuffer;
|
||||||
|
};
|
||||||
|
const encodePacket = ({ type, data }, supportsBinary, callback) => {
|
||||||
|
if (withNativeBlob && data instanceof Blob) {
|
||||||
|
if (supportsBinary) {
|
||||||
|
return callback(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return encodeBlobAsBase64(data, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (withNativeArrayBuffer &&
|
||||||
|
(data instanceof ArrayBuffer || isView(data))) {
|
||||||
|
if (supportsBinary) {
|
||||||
|
return callback(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return encodeBlobAsBase64(new Blob([data]), callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// plain string
|
||||||
|
return callback(PACKET_TYPES[type] + (data || ""));
|
||||||
|
};
|
||||||
|
const encodeBlobAsBase64 = (data, callback) => {
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onload = function () {
|
||||||
|
const content = fileReader.result.split(",")[1];
|
||||||
|
callback("b" + (content || ""));
|
||||||
|
};
|
||||||
|
return fileReader.readAsDataURL(data);
|
||||||
|
};
|
||||||
|
function toArray(data) {
|
||||||
|
if (data instanceof Uint8Array) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else if (data instanceof ArrayBuffer) {
|
||||||
|
return new Uint8Array(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let TEXT_ENCODER;
|
||||||
|
export function encodePacketToBinary(packet, callback) {
|
||||||
|
if (withNativeBlob && packet.data instanceof Blob) {
|
||||||
|
return packet.data.arrayBuffer().then(toArray).then(callback);
|
||||||
|
}
|
||||||
|
else if (withNativeArrayBuffer &&
|
||||||
|
(packet.data instanceof ArrayBuffer || isView(packet.data))) {
|
||||||
|
return callback(toArray(packet.data));
|
||||||
|
}
|
||||||
|
encodePacket(packet, false, (encoded) => {
|
||||||
|
if (!TEXT_ENCODER) {
|
||||||
|
TEXT_ENCODER = new TextEncoder();
|
||||||
|
}
|
||||||
|
callback(TEXT_ENCODER.encode(encoded));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export { encodePacket };
|
||||||
3
node_modules/engine.io-parser/build/esm/encodePacket.d.ts
generated
vendored
Normal file
3
node_modules/engine.io-parser/build/esm/encodePacket.d.ts
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { Packet, RawData } from "./commons.js";
|
||||||
|
export declare const encodePacket: ({ type, data }: Packet, supportsBinary: boolean, callback: (encodedPacket: RawData) => void) => void;
|
||||||
|
export declare function encodePacketToBinary(packet: Packet, callback: (encodedPacket: RawData) => void): void;
|
||||||
33
node_modules/engine.io-parser/build/esm/encodePacket.js
generated
vendored
Normal file
33
node_modules/engine.io-parser/build/esm/encodePacket.js
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { PACKET_TYPES } from "./commons.js";
|
||||||
|
export const encodePacket = ({ type, data }, supportsBinary, callback) => {
|
||||||
|
if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
|
||||||
|
return callback(supportsBinary ? data : "b" + toBuffer(data, true).toString("base64"));
|
||||||
|
}
|
||||||
|
// plain string
|
||||||
|
return callback(PACKET_TYPES[type] + (data || ""));
|
||||||
|
};
|
||||||
|
const toBuffer = (data, forceBufferConversion) => {
|
||||||
|
if (Buffer.isBuffer(data) ||
|
||||||
|
(data instanceof Uint8Array && !forceBufferConversion)) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else if (data instanceof ArrayBuffer) {
|
||||||
|
return Buffer.from(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let TEXT_ENCODER;
|
||||||
|
export function encodePacketToBinary(packet, callback) {
|
||||||
|
if (packet.data instanceof ArrayBuffer || ArrayBuffer.isView(packet.data)) {
|
||||||
|
return callback(toBuffer(packet.data, false));
|
||||||
|
}
|
||||||
|
encodePacket(packet, true, (encoded) => {
|
||||||
|
if (!TEXT_ENCODER) {
|
||||||
|
// lazily created for compatibility with Node.js 10
|
||||||
|
TEXT_ENCODER = new TextEncoder();
|
||||||
|
}
|
||||||
|
callback(TEXT_ENCODER.encode(encoded));
|
||||||
|
});
|
||||||
|
}
|
||||||
9
node_modules/engine.io-parser/build/esm/index.d.ts
generated
vendored
Normal file
9
node_modules/engine.io-parser/build/esm/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { encodePacket } from "./encodePacket.js";
|
||||||
|
import { decodePacket } from "./decodePacket.js";
|
||||||
|
import { Packet, PacketType, RawData, BinaryType } from "./commons.js";
|
||||||
|
declare const encodePayload: (packets: Packet[], callback: (encodedPayload: string) => void) => void;
|
||||||
|
declare const decodePayload: (encodedPayload: string, binaryType?: BinaryType) => Packet[];
|
||||||
|
export declare function createPacketEncoderStream(): any;
|
||||||
|
export declare function createPacketDecoderStream(maxPayload: number, binaryType: BinaryType): any;
|
||||||
|
export declare const protocol = 4;
|
||||||
|
export { encodePacket, encodePayload, decodePacket, decodePayload, Packet, PacketType, RawData, BinaryType, };
|
||||||
156
node_modules/engine.io-parser/build/esm/index.js
generated
vendored
Normal file
156
node_modules/engine.io-parser/build/esm/index.js
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import { encodePacket, encodePacketToBinary } from "./encodePacket.js";
|
||||||
|
import { decodePacket } from "./decodePacket.js";
|
||||||
|
import { ERROR_PACKET, } from "./commons.js";
|
||||||
|
const SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text
|
||||||
|
const encodePayload = (packets, callback) => {
|
||||||
|
// some packets may be added to the array while encoding, so the initial length must be saved
|
||||||
|
const length = packets.length;
|
||||||
|
const encodedPackets = new Array(length);
|
||||||
|
let count = 0;
|
||||||
|
packets.forEach((packet, i) => {
|
||||||
|
// force base64 encoding for binary packets
|
||||||
|
encodePacket(packet, false, (encodedPacket) => {
|
||||||
|
encodedPackets[i] = encodedPacket;
|
||||||
|
if (++count === length) {
|
||||||
|
callback(encodedPackets.join(SEPARATOR));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const decodePayload = (encodedPayload, binaryType) => {
|
||||||
|
const encodedPackets = encodedPayload.split(SEPARATOR);
|
||||||
|
const packets = [];
|
||||||
|
for (let i = 0; i < encodedPackets.length; i++) {
|
||||||
|
const decodedPacket = decodePacket(encodedPackets[i], binaryType);
|
||||||
|
packets.push(decodedPacket);
|
||||||
|
if (decodedPacket.type === "error") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return packets;
|
||||||
|
};
|
||||||
|
export function createPacketEncoderStream() {
|
||||||
|
return new TransformStream({
|
||||||
|
transform(packet, controller) {
|
||||||
|
encodePacketToBinary(packet, (encodedPacket) => {
|
||||||
|
const payloadLength = encodedPacket.length;
|
||||||
|
let header;
|
||||||
|
// inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
|
||||||
|
if (payloadLength < 126) {
|
||||||
|
header = new Uint8Array(1);
|
||||||
|
new DataView(header.buffer).setUint8(0, payloadLength);
|
||||||
|
}
|
||||||
|
else if (payloadLength < 65536) {
|
||||||
|
header = new Uint8Array(3);
|
||||||
|
const view = new DataView(header.buffer);
|
||||||
|
view.setUint8(0, 126);
|
||||||
|
view.setUint16(1, payloadLength);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
header = new Uint8Array(9);
|
||||||
|
const view = new DataView(header.buffer);
|
||||||
|
view.setUint8(0, 127);
|
||||||
|
view.setBigUint64(1, BigInt(payloadLength));
|
||||||
|
}
|
||||||
|
// first bit indicates whether the payload is plain text (0) or binary (1)
|
||||||
|
if (packet.data && typeof packet.data !== "string") {
|
||||||
|
header[0] |= 0x80;
|
||||||
|
}
|
||||||
|
controller.enqueue(header);
|
||||||
|
controller.enqueue(encodedPacket);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let TEXT_DECODER;
|
||||||
|
function totalLength(chunks) {
|
||||||
|
return chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
||||||
|
}
|
||||||
|
function concatChunks(chunks, size) {
|
||||||
|
if (chunks[0].length === size) {
|
||||||
|
return chunks.shift();
|
||||||
|
}
|
||||||
|
const buffer = new Uint8Array(size);
|
||||||
|
let j = 0;
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
buffer[i] = chunks[0][j++];
|
||||||
|
if (j === chunks[0].length) {
|
||||||
|
chunks.shift();
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chunks.length && j < chunks[0].length) {
|
||||||
|
chunks[0] = chunks[0].slice(j);
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
export function createPacketDecoderStream(maxPayload, binaryType) {
|
||||||
|
if (!TEXT_DECODER) {
|
||||||
|
TEXT_DECODER = new TextDecoder();
|
||||||
|
}
|
||||||
|
const chunks = [];
|
||||||
|
let state = 0 /* State.READ_HEADER */;
|
||||||
|
let expectedLength = -1;
|
||||||
|
let isBinary = false;
|
||||||
|
return new TransformStream({
|
||||||
|
transform(chunk, controller) {
|
||||||
|
chunks.push(chunk);
|
||||||
|
while (true) {
|
||||||
|
if (state === 0 /* State.READ_HEADER */) {
|
||||||
|
if (totalLength(chunks) < 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const header = concatChunks(chunks, 1);
|
||||||
|
isBinary = (header[0] & 0x80) === 0x80;
|
||||||
|
expectedLength = header[0] & 0x7f;
|
||||||
|
if (expectedLength < 126) {
|
||||||
|
state = 3 /* State.READ_PAYLOAD */;
|
||||||
|
}
|
||||||
|
else if (expectedLength === 126) {
|
||||||
|
state = 1 /* State.READ_EXTENDED_LENGTH_16 */;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state = 2 /* State.READ_EXTENDED_LENGTH_64 */;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state === 1 /* State.READ_EXTENDED_LENGTH_16 */) {
|
||||||
|
if (totalLength(chunks) < 2) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const headerArray = concatChunks(chunks, 2);
|
||||||
|
expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);
|
||||||
|
state = 3 /* State.READ_PAYLOAD */;
|
||||||
|
}
|
||||||
|
else if (state === 2 /* State.READ_EXTENDED_LENGTH_64 */) {
|
||||||
|
if (totalLength(chunks) < 8) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const headerArray = concatChunks(chunks, 8);
|
||||||
|
const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);
|
||||||
|
const n = view.getUint32(0);
|
||||||
|
if (n > Math.pow(2, 53 - 32) - 1) {
|
||||||
|
// the maximum safe integer in JavaScript is 2^53 - 1
|
||||||
|
controller.enqueue(ERROR_PACKET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
expectedLength = n * Math.pow(2, 32) + view.getUint32(4);
|
||||||
|
state = 3 /* State.READ_PAYLOAD */;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (totalLength(chunks) < expectedLength) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const data = concatChunks(chunks, expectedLength);
|
||||||
|
controller.enqueue(decodePacket(isBinary ? data : TEXT_DECODER.decode(data), binaryType));
|
||||||
|
state = 0 /* State.READ_HEADER */;
|
||||||
|
}
|
||||||
|
if (expectedLength === 0 || expectedLength > maxPayload) {
|
||||||
|
controller.enqueue(ERROR_PACKET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export const protocol = 4;
|
||||||
|
export { encodePacket, encodePayload, decodePacket, decodePayload, };
|
||||||
8
node_modules/engine.io-parser/build/esm/package.json
generated
vendored
Normal file
8
node_modules/engine.io-parser/build/esm/package.json
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "engine.io-parser",
|
||||||
|
"type": "module",
|
||||||
|
"browser": {
|
||||||
|
"./encodePacket.js": "./encodePacket.browser.js",
|
||||||
|
"./decodePacket.js": "./decodePacket.browser.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
46
node_modules/engine.io-parser/package.json
generated
vendored
Normal file
46
node_modules/engine.io-parser/package.json
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "engine.io-parser",
|
||||||
|
"description": "Parser for the client for the realtime Engine",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "5.2.3",
|
||||||
|
"main": "./build/cjs/index.js",
|
||||||
|
"module": "./build/esm/index.js",
|
||||||
|
"exports": {
|
||||||
|
"import": "./build/esm/index.js",
|
||||||
|
"require": "./build/cjs/index.js"
|
||||||
|
},
|
||||||
|
"types": "build/esm/index.d.ts",
|
||||||
|
"devDependencies": {
|
||||||
|
"prettier": "^3.3.2"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"compile": "rimraf ./build && tsc && tsc -p tsconfig.esm.json && ./postcompile.sh",
|
||||||
|
"test": "npm run format:check && npm run compile && if test \"$BROWSERS\" = \"1\" ; then npm run test:browser; else npm run test:node; fi",
|
||||||
|
"test:node": "nyc mocha -r ts-node/register test/index.ts",
|
||||||
|
"test:browser": "zuul test/index.ts --no-coverage",
|
||||||
|
"format:check": "prettier --check 'lib/**/*.ts' 'test/**/*.ts'",
|
||||||
|
"format:fix": "prettier --write 'lib/**/*.ts' 'test/**/*.ts'",
|
||||||
|
"prepack": "npm run compile"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/socketio/socket.io/tree/main/packages/engine.io-parser#readme",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/socketio/socket.io.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/socketio/socket.io/issues"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"build/"
|
||||||
|
],
|
||||||
|
"browser": {
|
||||||
|
"./test/node": "./test/browser",
|
||||||
|
"./build/esm/encodePacket.js": "./build/esm/encodePacket.browser.js",
|
||||||
|
"./build/esm/decodePacket.js": "./build/esm/decodePacket.browser.js",
|
||||||
|
"./build/cjs/encodePacket.js": "./build/cjs/encodePacket.browser.js",
|
||||||
|
"./build/cjs/decodePacket.js": "./build/cjs/decodePacket.browser.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
19
node_modules/engine.io/LICENSE
generated
vendored
Normal file
19
node_modules/engine.io/LICENSE
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014-present Guillermo Rauch and Socket.IO contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
and associated documentation files (the 'Software'), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||||
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||||
|
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
603
node_modules/engine.io/README.md
generated
vendored
Normal file
603
node_modules/engine.io/README.md
generated
vendored
Normal file
@ -0,0 +1,603 @@
|
|||||||
|
|
||||||
|
# Engine.IO: the realtime engine
|
||||||
|
|
||||||
|
[](https://github.com/socketio/engine.io/actions)
|
||||||
|
[](http://badge.fury.io/js/engine.io)
|
||||||
|
|
||||||
|
`Engine.IO` is the implementation of transport-based
|
||||||
|
cross-browser/cross-device bi-directional communication layer for
|
||||||
|
[Socket.IO](http://github.com/socketio/socket.io).
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
### Server
|
||||||
|
|
||||||
|
#### (A) Listening on a port
|
||||||
|
|
||||||
|
```js
|
||||||
|
const engine = require('engine.io');
|
||||||
|
const server = engine.listen(80);
|
||||||
|
|
||||||
|
server.on('connection', socket => {
|
||||||
|
socket.send('utf 8 string');
|
||||||
|
socket.send(Buffer.from([0, 1, 2, 3, 4, 5])); // binary data
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### (B) Intercepting requests for a http.Server
|
||||||
|
|
||||||
|
```js
|
||||||
|
const engine = require('engine.io');
|
||||||
|
const http = require('http').createServer().listen(3000);
|
||||||
|
const server = engine.attach(http);
|
||||||
|
|
||||||
|
server.on('connection', socket => {
|
||||||
|
socket.on('message', data => { });
|
||||||
|
socket.on('close', () => { });
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### (C) Passing in requests
|
||||||
|
|
||||||
|
```js
|
||||||
|
const engine = require('engine.io');
|
||||||
|
const server = new engine.Server();
|
||||||
|
|
||||||
|
server.on('connection', socket => {
|
||||||
|
socket.send('hi');
|
||||||
|
});
|
||||||
|
|
||||||
|
// …
|
||||||
|
httpServer.on('upgrade', (req, socket, head) => {
|
||||||
|
server.handleUpgrade(req, socket, head);
|
||||||
|
});
|
||||||
|
|
||||||
|
httpServer.on('request', (req, res) => {
|
||||||
|
server.handleRequest(req, res);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="/path/to/engine.io.js"></script>
|
||||||
|
<script>
|
||||||
|
const socket = new eio.Socket('ws://localhost/');
|
||||||
|
socket.on('open', () => {
|
||||||
|
socket.on('message', data => {});
|
||||||
|
socket.on('close', () => {});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information on the client refer to the
|
||||||
|
[engine-client](http://github.com/socketio/engine.io-client) repository.
|
||||||
|
|
||||||
|
## What features does it have?
|
||||||
|
|
||||||
|
- **Maximum reliability**. Connections are established even in the presence of:
|
||||||
|
- proxies and load balancers.
|
||||||
|
- personal firewall and antivirus software.
|
||||||
|
- for more information refer to **Goals** and **Architecture** sections
|
||||||
|
- **Minimal client size** aided by:
|
||||||
|
- lazy loading of flash transports.
|
||||||
|
- lack of redundant transports.
|
||||||
|
- **Scalable**
|
||||||
|
- load balancer friendly
|
||||||
|
- **Future proof**
|
||||||
|
- **100% Node.JS core style**
|
||||||
|
- No API sugar (left for higher level projects)
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Server
|
||||||
|
|
||||||
|
<hr><br>
|
||||||
|
|
||||||
|
#### Top-level
|
||||||
|
|
||||||
|
These are exposed by `require('engine.io')`:
|
||||||
|
|
||||||
|
##### Events
|
||||||
|
|
||||||
|
- `flush`
|
||||||
|
- Called when a socket buffer is being flushed.
|
||||||
|
- **Arguments**
|
||||||
|
- `Socket`: socket being flushed
|
||||||
|
- `Array`: write buffer
|
||||||
|
- `drain`
|
||||||
|
- Called when a socket buffer is drained
|
||||||
|
- **Arguments**
|
||||||
|
- `Socket`: socket being flushed
|
||||||
|
|
||||||
|
##### Properties
|
||||||
|
|
||||||
|
- `protocol` _(Number)_: protocol revision number
|
||||||
|
- `Server`: Server class constructor
|
||||||
|
- `Socket`: Socket class constructor
|
||||||
|
- `Transport` _(Function)_: transport constructor
|
||||||
|
- `transports` _(Object)_: map of available transports
|
||||||
|
|
||||||
|
##### Methods
|
||||||
|
|
||||||
|
- `()`
|
||||||
|
- Returns a new `Server` instance. If the first argument is an `http.Server` then the
|
||||||
|
new `Server` instance will be attached to it. Otherwise, the arguments are passed
|
||||||
|
directly to the `Server` constructor.
|
||||||
|
- **Parameters**
|
||||||
|
- `http.Server`: optional, server to attach to.
|
||||||
|
- `Object`: optional, options object (see `Server#constructor` api docs below)
|
||||||
|
|
||||||
|
The following are identical ways to instantiate a server and then attach it.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const httpServer; // previously created with `http.createServer();` from node.js api.
|
||||||
|
|
||||||
|
// create a server first, and then attach
|
||||||
|
const eioServer = require('engine.io').Server();
|
||||||
|
eioServer.attach(httpServer);
|
||||||
|
|
||||||
|
// or call the module as a function to get `Server`
|
||||||
|
const eioServer = require('engine.io')();
|
||||||
|
eioServer.attach(httpServer);
|
||||||
|
|
||||||
|
// immediately attach
|
||||||
|
const eioServer = require('engine.io')(httpServer);
|
||||||
|
|
||||||
|
// with custom options
|
||||||
|
const eioServer = require('engine.io')(httpServer, {
|
||||||
|
maxHttpBufferSize: 1e3
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- `listen`
|
||||||
|
- Creates an `http.Server` which listens on the given port and attaches WS
|
||||||
|
to it. It returns `501 Not Implemented` for regular http requests.
|
||||||
|
- **Parameters**
|
||||||
|
- `Number`: port to listen on.
|
||||||
|
- `Object`: optional, options object
|
||||||
|
- `Function`: callback for `listen`.
|
||||||
|
- **Options**
|
||||||
|
- All options from `Server.attach` method, documented below.
|
||||||
|
- **Additionally** See Server `constructor` below for options you can pass for creating the new Server
|
||||||
|
- **Returns** `Server`
|
||||||
|
|
||||||
|
```js
|
||||||
|
const engine = require('engine.io');
|
||||||
|
const server = engine.listen(3000, {
|
||||||
|
pingTimeout: 2000,
|
||||||
|
pingInterval: 10000
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on('connection', /* ... */);
|
||||||
|
```
|
||||||
|
|
||||||
|
- `attach`
|
||||||
|
- Captures `upgrade` requests for a `http.Server`. In other words, makes
|
||||||
|
a regular http.Server WebSocket-compatible.
|
||||||
|
- **Parameters**
|
||||||
|
- `http.Server`: server to attach to.
|
||||||
|
- `Object`: optional, options object
|
||||||
|
- **Options**
|
||||||
|
- All options from `Server.attach` method, documented below.
|
||||||
|
- **Additionally** See Server `constructor` below for options you can pass for creating the new Server
|
||||||
|
- **Returns** `Server` a new Server instance.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const engine = require('engine.io');
|
||||||
|
const httpServer = require('http').createServer().listen(3000);
|
||||||
|
const server = engine.attach(httpServer, {
|
||||||
|
wsEngine: require('eiows').Server // requires having eiows as dependency
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on('connection', /* ... */);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Server
|
||||||
|
|
||||||
|
The main server/manager. _Inherits from EventEmitter_.
|
||||||
|
|
||||||
|
##### Events
|
||||||
|
|
||||||
|
- `connection`
|
||||||
|
- Fired when a new connection is established.
|
||||||
|
- **Arguments**
|
||||||
|
- `Socket`: a Socket object
|
||||||
|
|
||||||
|
- `initial_headers`
|
||||||
|
- Fired on the first request of the connection, before writing the response headers
|
||||||
|
- **Arguments**
|
||||||
|
- `headers` (`Object`): a hash of headers
|
||||||
|
- `req` (`http.IncomingMessage`): the request
|
||||||
|
|
||||||
|
- `headers`
|
||||||
|
- Fired on the all requests of the connection, before writing the response headers
|
||||||
|
- **Arguments**
|
||||||
|
- `headers` (`Object`): a hash of headers
|
||||||
|
- `req` (`http.IncomingMessage`): the request
|
||||||
|
|
||||||
|
- `connection_error`
|
||||||
|
- Fired when an error occurs when establishing the connection.
|
||||||
|
- **Arguments**
|
||||||
|
- `error`: an object with following properties:
|
||||||
|
- `req` (`http.IncomingMessage`): the request that was dropped
|
||||||
|
- `code` (`Number`): one of `Server.errors`
|
||||||
|
- `message` (`string`): one of `Server.errorMessages`
|
||||||
|
- `context` (`Object`): extra info about the error
|
||||||
|
|
||||||
|
| Code | Message |
|
||||||
|
| ---- | ------- |
|
||||||
|
| 0 | "Transport unknown"
|
||||||
|
| 1 | "Session ID unknown"
|
||||||
|
| 2 | "Bad handshake method"
|
||||||
|
| 3 | "Bad request"
|
||||||
|
| 4 | "Forbidden"
|
||||||
|
| 5 | "Unsupported protocol version"
|
||||||
|
|
||||||
|
|
||||||
|
##### Properties
|
||||||
|
|
||||||
|
**Important**: if you plan to use Engine.IO in a scalable way, please
|
||||||
|
keep in mind the properties below will only reflect the clients connected
|
||||||
|
to a single process.
|
||||||
|
|
||||||
|
- `clients` _(Object)_: hash of connected clients by id.
|
||||||
|
- `clientsCount` _(Number)_: number of connected clients.
|
||||||
|
|
||||||
|
##### Methods
|
||||||
|
|
||||||
|
- **constructor**
|
||||||
|
- Initializes the server
|
||||||
|
- **Parameters**
|
||||||
|
- `Object`: optional, options object
|
||||||
|
- **Options**
|
||||||
|
- `pingTimeout` (`Number`): how many ms without a pong packet to
|
||||||
|
consider the connection closed (`20000`)
|
||||||
|
- `pingInterval` (`Number`): how many ms before sending a new ping
|
||||||
|
packet (`25000`)
|
||||||
|
- `upgradeTimeout` (`Number`): how many ms before an uncompleted transport upgrade is cancelled (`10000`)
|
||||||
|
- `maxHttpBufferSize` (`Number`): how many bytes or characters a message
|
||||||
|
can be, before closing the session (to avoid DoS). Default
|
||||||
|
value is `1E6`.
|
||||||
|
- `allowRequest` (`Function`): 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.
|
||||||
|
- `transports` (`<Array> String`): transports to allow connections
|
||||||
|
to (`['polling', 'websocket']`)
|
||||||
|
- `allowUpgrades` (`Boolean`): whether to allow transport upgrades
|
||||||
|
(`true`)
|
||||||
|
- `perMessageDeflate` (`Object|Boolean`): parameters of the WebSocket permessage-deflate extension
|
||||||
|
(see [ws module](https://github.com/einaros/ws) api docs). Set to `true` to enable. (defaults to `false`)
|
||||||
|
- `threshold` (`Number`): data is compressed only if the byte size is above this value (`1024`)
|
||||||
|
- `httpCompression` (`Object|Boolean`): parameters of the http compression for the polling transports
|
||||||
|
(see [zlib](http://nodejs.org/api/zlib.html#zlib_options) api docs). Set to `false` to disable. (`true`)
|
||||||
|
- `threshold` (`Number`): data is compressed only if the byte size is above this value (`1024`)
|
||||||
|
- `cookie` (`Object|Boolean`): 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`).
|
||||||
|
See [here](https://github.com/jshttp/cookie#options-1) for all supported options.
|
||||||
|
- `wsEngine` (`Function`): what WebSocket server implementation to use. Specified module must conform to the `ws` interface (see [ws module api docs](https://github.com/websockets/ws/blob/master/doc/ws.md)). Default value is `ws`. An alternative c++ addon is also available by installing `eiows` module.
|
||||||
|
- `cors` (`Object`): the options that will be forwarded to the cors module. See [there](https://github.com/expressjs/cors#configuration-options) for all available options. Defaults to no CORS allowed.
|
||||||
|
- `initialPacket` (`Object`): an optional packet which will be concatenated to the handshake packet emitted by Engine.IO.
|
||||||
|
- `allowEIO3` (`Boolean`): whether to support v3 Engine.IO clients (defaults to `false`)
|
||||||
|
- `close`
|
||||||
|
- Closes all clients
|
||||||
|
- **Returns** `Server` for chaining
|
||||||
|
- `handleRequest`
|
||||||
|
- Called internally when a `Engine` request is intercepted.
|
||||||
|
- **Parameters**
|
||||||
|
- `http.IncomingMessage`: a node request object
|
||||||
|
- `http.ServerResponse`: a node response object
|
||||||
|
- **Returns** `Server` for chaining
|
||||||
|
- `handleUpgrade`
|
||||||
|
- Called internally when a `Engine` ws upgrade is intercepted.
|
||||||
|
- **Parameters** (same as `upgrade` event)
|
||||||
|
- `http.IncomingMessage`: a node request object
|
||||||
|
- `net.Stream`: TCP socket for the request
|
||||||
|
- `Buffer`: legacy tail bytes
|
||||||
|
- **Returns** `Server` for chaining
|
||||||
|
- `attach`
|
||||||
|
- Attach this Server instance to an `http.Server`
|
||||||
|
- Captures `upgrade` requests for a `http.Server`. In other words, makes
|
||||||
|
a regular http.Server WebSocket-compatible.
|
||||||
|
- **Parameters**
|
||||||
|
- `http.Server`: server to attach to.
|
||||||
|
- `Object`: optional, options object
|
||||||
|
- **Options**
|
||||||
|
- `path` (`String`): name of the path to capture (`/engine.io`).
|
||||||
|
- `destroyUpgrade` (`Boolean`): destroy unhandled upgrade requests (`true`)
|
||||||
|
- `destroyUpgradeTimeout` (`Number`): milliseconds after which unhandled requests are ended (`1000`)
|
||||||
|
- `generateId`
|
||||||
|
- Generate a socket id.
|
||||||
|
- Overwrite this method to generate your custom socket id.
|
||||||
|
- **Parameters**
|
||||||
|
- `http.IncomingMessage`: a node request object
|
||||||
|
- **Returns** A socket id for connected client.
|
||||||
|
|
||||||
|
<hr><br>
|
||||||
|
|
||||||
|
#### Socket
|
||||||
|
|
||||||
|
A representation of a client. _Inherits from EventEmitter_.
|
||||||
|
|
||||||
|
##### Events
|
||||||
|
|
||||||
|
- `close`
|
||||||
|
- Fired when the client is disconnected.
|
||||||
|
- **Arguments**
|
||||||
|
- `String`: reason for closing
|
||||||
|
- `Object`: description object (optional)
|
||||||
|
- `message`
|
||||||
|
- Fired when the client sends a message.
|
||||||
|
- **Arguments**
|
||||||
|
- `String` or `Buffer`: Unicode string or Buffer with binary contents
|
||||||
|
- `error`
|
||||||
|
- Fired when an error occurs.
|
||||||
|
- **Arguments**
|
||||||
|
- `Error`: error object
|
||||||
|
- `upgrading`
|
||||||
|
- Fired when the client starts the upgrade to a better transport like WebSocket.
|
||||||
|
- **Arguments**
|
||||||
|
- `Object`: the transport
|
||||||
|
- `upgrade`
|
||||||
|
- Fired when the client completes the upgrade to a better transport like WebSocket.
|
||||||
|
- **Arguments**
|
||||||
|
- `Object`: the transport
|
||||||
|
- `flush`
|
||||||
|
- Called when the write buffer is being flushed.
|
||||||
|
- **Arguments**
|
||||||
|
- `Array`: write buffer
|
||||||
|
- `drain`
|
||||||
|
- Called when the write buffer is drained
|
||||||
|
- `packet`
|
||||||
|
- Called when a socket received a packet (`message`, `ping`)
|
||||||
|
- **Arguments**
|
||||||
|
- `type`: packet type
|
||||||
|
- `data`: packet data (if type is message)
|
||||||
|
- `packetCreate`
|
||||||
|
- Called before a socket sends a packet (`message`, `ping`)
|
||||||
|
- **Arguments**
|
||||||
|
- `type`: packet type
|
||||||
|
- `data`: packet data (if type is message)
|
||||||
|
- `heartbeat`
|
||||||
|
- Called when `ping` or `pong` packed is received (depends of client version)
|
||||||
|
|
||||||
|
##### Properties
|
||||||
|
|
||||||
|
- `id` _(String)_: unique identifier
|
||||||
|
- `server` _(Server)_: engine parent reference
|
||||||
|
- `request` _(http.IncomingMessage)_: request that originated the Socket
|
||||||
|
- `upgraded` _(Boolean)_: whether the transport has been upgraded
|
||||||
|
- `readyState` _(String)_: opening|open|closing|closed
|
||||||
|
- `transport` _(Transport)_: transport reference
|
||||||
|
|
||||||
|
##### Methods
|
||||||
|
|
||||||
|
- `send`:
|
||||||
|
- Sends a message, performing `message = toString(arguments[0])` unless
|
||||||
|
sending binary data, which is sent as is.
|
||||||
|
- **Parameters**
|
||||||
|
- `String` | `Buffer` | `ArrayBuffer` | `ArrayBufferView`: a string or any object implementing `toString()`, with outgoing data, or a Buffer or ArrayBuffer with binary data. Also any ArrayBufferView can be sent as is.
|
||||||
|
- `Object`: optional, options object
|
||||||
|
- `Function`: optional, a callback executed when the message gets flushed out by the transport
|
||||||
|
- **Options**
|
||||||
|
- `compress` (`Boolean`): whether to compress sending data. This option might be ignored and forced to be `true` when using polling. (`true`)
|
||||||
|
- **Returns** `Socket` for chaining
|
||||||
|
- `close`
|
||||||
|
- Disconnects the client
|
||||||
|
- **Returns** `Socket` for chaining
|
||||||
|
|
||||||
|
### Client
|
||||||
|
|
||||||
|
<hr><br>
|
||||||
|
|
||||||
|
Exposed in the `eio` global namespace (in the browser), or by
|
||||||
|
`require('engine.io-client')` (in Node.JS).
|
||||||
|
|
||||||
|
For the client API refer to the
|
||||||
|
[engine-client](http://github.com/learnboost/engine.io-client) repository.
|
||||||
|
|
||||||
|
## Debug / logging
|
||||||
|
|
||||||
|
Engine.IO is powered by [debug](http://github.com/visionmedia/debug).
|
||||||
|
In order to see all the debug output, run your app with the environment variable
|
||||||
|
`DEBUG` including the desired scope.
|
||||||
|
|
||||||
|
To see the output from all of Engine.IO's debugging scopes you can use:
|
||||||
|
|
||||||
|
```
|
||||||
|
DEBUG=engine* node myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Transports
|
||||||
|
|
||||||
|
- `polling`: XHR / JSONP polling transport.
|
||||||
|
- `websocket`: WebSocket transport.
|
||||||
|
|
||||||
|
## Plugins
|
||||||
|
|
||||||
|
- [engine.io-conflation](https://github.com/EugenDueck/engine.io-conflation): Makes **conflation and aggregation** of messages straightforward.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
The support channels for `engine.io` are the same as `socket.io`:
|
||||||
|
- irc.freenode.net **#socket.io**
|
||||||
|
- [Google Groups](http://groups.google.com/group/socket_io)
|
||||||
|
- [Website](http://socket.io)
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
To contribute patches, run tests or benchmarks, make sure to clone the
|
||||||
|
repository:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone git://github.com/LearnBoost/engine.io.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Then:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd engine.io
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Tests run with `npm test`. It runs the server tests that are aided by
|
||||||
|
the usage of `engine.io-client`.
|
||||||
|
|
||||||
|
Make sure `npm install` is run first.
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
The main goal of `Engine` is ensuring the most reliable realtime communication.
|
||||||
|
Unlike the previous Socket.IO core, it always establishes a long-polling
|
||||||
|
connection first, then tries to upgrade to better transports that are "tested" on
|
||||||
|
the side.
|
||||||
|
|
||||||
|
During the lifetime of the Socket.IO projects, we've found countless drawbacks
|
||||||
|
to relying on `HTML5 WebSocket` or `Flash Socket` as the first connection
|
||||||
|
mechanisms.
|
||||||
|
|
||||||
|
Both are clearly the _right way_ of establishing a bidirectional communication,
|
||||||
|
with HTML5 WebSocket being the way of the future. However, to answer most business
|
||||||
|
needs, alternative traditional HTTP 1.1 mechanisms are just as good as delivering
|
||||||
|
the same solution.
|
||||||
|
|
||||||
|
WebSocket based connections have two fundamental benefits:
|
||||||
|
|
||||||
|
1. **Better server performance**
|
||||||
|
- _A: Load balancers_<br>
|
||||||
|
Load balancing a long polling connection poses a serious architectural nightmare
|
||||||
|
since requests can come from any number of open sockets by the user agent, but
|
||||||
|
they all need to be routed to the process and computer that owns the `Engine`
|
||||||
|
connection. This negatively impacts RAM and CPU usage.
|
||||||
|
- _B: Network traffic_<br>
|
||||||
|
WebSocket is designed around the premise that each message frame has to be
|
||||||
|
surrounded by the least amount of data. In HTTP 1.1 transports, each message
|
||||||
|
frame is surrounded by HTTP headers and chunked encoding frames. If you try to
|
||||||
|
send the message _"Hello world"_ with xhr-polling, the message ultimately
|
||||||
|
becomes larger than if you were to send it with WebSocket.
|
||||||
|
- _C: Lightweight parser_<br>
|
||||||
|
As an effect of **B**, the server has to do a lot more work to parse the network
|
||||||
|
data and figure out the message when traditional HTTP requests are used
|
||||||
|
(as in long polling). This means that another advantage of WebSocket is
|
||||||
|
less server CPU usage.
|
||||||
|
|
||||||
|
2. **Better user experience**
|
||||||
|
|
||||||
|
Due to the reasons stated in point **1**, the most important effect of being able
|
||||||
|
to establish a WebSocket connection is raw data transfer speed, which translates
|
||||||
|
in _some_ cases in better user experience.
|
||||||
|
|
||||||
|
Applications with heavy realtime interaction (such as games) will benefit greatly,
|
||||||
|
whereas applications like realtime chat (Gmail/Facebook), newsfeeds (Facebook) or
|
||||||
|
timelines (Twitter) will have negligible user experience improvements.
|
||||||
|
|
||||||
|
Having said this, attempting to establish a WebSocket connection directly so far has
|
||||||
|
proven problematic:
|
||||||
|
|
||||||
|
1. **Proxies**<br>
|
||||||
|
Many corporate proxies block WebSocket traffic.
|
||||||
|
|
||||||
|
2. **Personal firewall and antivirus software**<br>
|
||||||
|
As a result of our research, we've found that at least 3 personal security
|
||||||
|
applications block WebSocket traffic.
|
||||||
|
|
||||||
|
3. **Cloud application platforms**<br>
|
||||||
|
Platforms like Heroku or No.de have had trouble keeping up with the fast-paced
|
||||||
|
nature of the evolution of the WebSocket protocol. Applications therefore end up
|
||||||
|
inevitably using long polling, but the seamless installation experience of
|
||||||
|
Socket.IO we strive for (_"require() it and it just works"_) disappears.
|
||||||
|
|
||||||
|
Some of these problems have solutions. In the case of proxies and personal programs,
|
||||||
|
however, the solutions many times involve upgrading software. Experience has shown
|
||||||
|
that relying on client software upgrades to deliver a business solution is
|
||||||
|
fruitless: the very existence of this project has to do with a fragmented panorama
|
||||||
|
of user agent distribution, with clients connecting with latest versions of the most
|
||||||
|
modern user agents (Chrome, Firefox and Safari), but others with versions as low as
|
||||||
|
IE 5.5.
|
||||||
|
|
||||||
|
From the user perspective, an unsuccessful WebSocket connection can translate in
|
||||||
|
up to at least 10 seconds of waiting for the realtime application to begin
|
||||||
|
exchanging data. This **perceptively** hurts user experience.
|
||||||
|
|
||||||
|
To summarize, **Engine** focuses on reliability and user experience first, marginal
|
||||||
|
potential UX improvements and increased server performance second. `Engine` is the
|
||||||
|
result of all the lessons learned with WebSocket in the wild.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The main premise of `Engine`, and the core of its existence, is the ability to
|
||||||
|
swap transports on the fly. A connection starts as xhr-polling, but it can
|
||||||
|
switch to WebSocket.
|
||||||
|
|
||||||
|
The central problem this poses is: how do we switch transports without losing
|
||||||
|
messages?
|
||||||
|
|
||||||
|
`Engine` only switches from polling to another transport in between polling
|
||||||
|
cycles. Since the server closes the connection after a certain timeout when
|
||||||
|
there's no activity, and the polling transport implementation buffers messages
|
||||||
|
in between connections, this ensures no message loss and optimal performance.
|
||||||
|
|
||||||
|
Another benefit of this design is that we workaround almost all the limitations
|
||||||
|
of **Flash Socket**, such as slow connection times, increased file size (we can
|
||||||
|
safely lazy load it without hurting user experience), etc.
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### Can I use engine without Socket.IO ?
|
||||||
|
|
||||||
|
Absolutely. Although the recommended framework for building realtime applications
|
||||||
|
is Socket.IO, since it provides fundamental features for real-world applications
|
||||||
|
such as multiplexing, reconnection support, etc.
|
||||||
|
|
||||||
|
`Engine` is to Socket.IO what Connect is to Express. An essential piece for building
|
||||||
|
realtime frameworks, but something you _probably_ won't be using for building
|
||||||
|
actual applications.
|
||||||
|
|
||||||
|
### Does the server serve the client?
|
||||||
|
|
||||||
|
No. The main reason is that `Engine` is meant to be bundled with frameworks.
|
||||||
|
Socket.IO includes `Engine`, therefore serving two clients is not necessary. If
|
||||||
|
you use Socket.IO, including
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="/socket.io/socket.io.js">
|
||||||
|
```
|
||||||
|
|
||||||
|
has you covered.
|
||||||
|
|
||||||
|
### Can I implement `Engine` in other languages?
|
||||||
|
|
||||||
|
Absolutely. The [engine.io-protocol](https://github.com/socketio/engine.io-protocol)
|
||||||
|
repository contains the most up-to-date description of the specification
|
||||||
|
at all times.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Guillermo Rauch <guillermo@learnboost.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
113
node_modules/engine.io/build/contrib/types.cookie.d.ts
generated
vendored
Normal file
113
node_modules/engine.io/build/contrib/types.cookie.d.ts
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* Basic HTTP cookie parser and serializer for HTTP servers.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Additional serialization options
|
||||||
|
*/
|
||||||
|
export interface CookieSerializeOptions {
|
||||||
|
/**
|
||||||
|
* Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.3|Domain Set-Cookie attribute}. By default, no
|
||||||
|
* domain is set, and most clients will consider the cookie to apply to only
|
||||||
|
* the current domain.
|
||||||
|
*/
|
||||||
|
domain?: string | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies a function that will be used to encode a cookie's value. Since
|
||||||
|
* value of a cookie has a limited character set (and must be a simple
|
||||||
|
* string), this function can be used to encode a value into a string suited
|
||||||
|
* for a cookie's value.
|
||||||
|
*
|
||||||
|
* The default function is the global `encodeURIComponent`, which will
|
||||||
|
* encode a JavaScript string into UTF-8 byte sequences and then URL-encode
|
||||||
|
* any that fall outside of the cookie range.
|
||||||
|
*/
|
||||||
|
encode?(value: string): string;
|
||||||
|
/**
|
||||||
|
* Specifies the `Date` object to be the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.1|`Expires` `Set-Cookie` attribute}. By default,
|
||||||
|
* no expiration is set, and most clients will consider this a "non-persistent cookie" and will delete
|
||||||
|
* it on a condition like exiting a web browser application.
|
||||||
|
*
|
||||||
|
* *Note* the {@link https://tools.ietf.org/html/rfc6265#section-5.3|cookie storage model specification}
|
||||||
|
* states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is
|
||||||
|
* possible not all clients by obey this, so if both are set, they should
|
||||||
|
* point to the same date and time.
|
||||||
|
*/
|
||||||
|
expires?: Date | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies the boolean value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.6|`HttpOnly` `Set-Cookie` attribute}.
|
||||||
|
* When truthy, the `HttpOnly` attribute is set, otherwise it is not. By
|
||||||
|
* default, the `HttpOnly` attribute is not set.
|
||||||
|
*
|
||||||
|
* *Note* be careful when setting this to true, as compliant clients will
|
||||||
|
* not allow client-side JavaScript to see the cookie in `document.cookie`.
|
||||||
|
*/
|
||||||
|
httpOnly?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies the number (in seconds) to be the value for the `Max-Age`
|
||||||
|
* `Set-Cookie` attribute. The given number will be converted to an integer
|
||||||
|
* by rounding down. By default, no maximum age is set.
|
||||||
|
*
|
||||||
|
* *Note* the {@link https://tools.ietf.org/html/rfc6265#section-5.3|cookie storage model specification}
|
||||||
|
* states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is
|
||||||
|
* possible not all clients by obey this, so if both are set, they should
|
||||||
|
* point to the same date and time.
|
||||||
|
*/
|
||||||
|
maxAge?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies)
|
||||||
|
* attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the
|
||||||
|
* `Partitioned` attribute is not set.
|
||||||
|
*
|
||||||
|
* **note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||||
|
* This also means many clients may ignore this attribute until they understand it.
|
||||||
|
*
|
||||||
|
* More information about can be found in [the proposal](https://github.com/privacycg/CHIPS)
|
||||||
|
*/
|
||||||
|
partitioned?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4|`Path` `Set-Cookie` attribute}.
|
||||||
|
* By default, the path is considered the "default path".
|
||||||
|
*/
|
||||||
|
path?: string | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1].
|
||||||
|
*
|
||||||
|
* - `'low'` will set the `Priority` attribute to `Low`.
|
||||||
|
* - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
|
||||||
|
* - `'high'` will set the `Priority` attribute to `High`.
|
||||||
|
*
|
||||||
|
* More information about the different priority levels can be found in
|
||||||
|
* [the specification][rfc-west-cookie-priority-00-4.1].
|
||||||
|
*
|
||||||
|
* **note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||||
|
* This also means many clients may ignore this attribute until they understand it.
|
||||||
|
*/
|
||||||
|
priority?: "low" | "medium" | "high" | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies the boolean or string to be the value for the {@link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7|`SameSite` `Set-Cookie` attribute}.
|
||||||
|
*
|
||||||
|
* - `true` will set the `SameSite` attribute to `Strict` for strict same
|
||||||
|
* site enforcement.
|
||||||
|
* - `false` will not set the `SameSite` attribute.
|
||||||
|
* - `'lax'` will set the `SameSite` attribute to Lax for lax same site
|
||||||
|
* enforcement.
|
||||||
|
* - `'strict'` will set the `SameSite` attribute to Strict for strict same
|
||||||
|
* site enforcement.
|
||||||
|
* - `'none'` will set the SameSite attribute to None for an explicit
|
||||||
|
* cross-site cookie.
|
||||||
|
*
|
||||||
|
* More information about the different enforcement levels can be found in {@link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7|the specification}.
|
||||||
|
*
|
||||||
|
* *note* This is an attribute that has not yet been fully standardized, and may change in the future. This also means many clients may ignore this attribute until they understand it.
|
||||||
|
*/
|
||||||
|
sameSite?: true | false | "lax" | "strict" | "none" | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies the boolean value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.5|`Secure` `Set-Cookie` attribute}. When truthy, the
|
||||||
|
* `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set.
|
||||||
|
*
|
||||||
|
* *Note* be careful when setting this to `true`, as compliant clients will
|
||||||
|
* not send the cookie back to the server in the future if the browser does
|
||||||
|
* not have an HTTPS connection.
|
||||||
|
*/
|
||||||
|
secure?: boolean | undefined;
|
||||||
|
}
|
||||||
6
node_modules/engine.io/build/contrib/types.cookie.js
generated
vendored
Normal file
6
node_modules/engine.io/build/contrib/types.cookie.js
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
"use strict";
|
||||||
|
// imported from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b83cf9ef8b044e69f05b2a00aa7c6cb767a9acd2/types/cookie/index.d.ts (now deleted)
|
||||||
|
/**
|
||||||
|
* Basic HTTP cookie parser and serializer for HTTP servers.
|
||||||
|
*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
27
node_modules/engine.io/build/engine.io.d.ts
generated
vendored
Normal file
27
node_modules/engine.io/build/engine.io.d.ts
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { Server as HttpServer } from "http";
|
||||||
|
import { Server, AttachOptions, ServerOptions } from "./server";
|
||||||
|
import transports from "./transports/index";
|
||||||
|
import * as parser from "engine.io-parser";
|
||||||
|
export { Server, transports, listen, attach, parser };
|
||||||
|
export type { AttachOptions, ServerOptions, BaseServer, ErrorCallback, } from "./server";
|
||||||
|
export { uServer } from "./userver";
|
||||||
|
export { Socket } from "./socket";
|
||||||
|
export { Transport } from "./transport";
|
||||||
|
export declare const protocol = 4;
|
||||||
|
/**
|
||||||
|
* Creates an http.Server exclusively used for WS upgrades, and starts listening.
|
||||||
|
*
|
||||||
|
* @param port
|
||||||
|
* @param options
|
||||||
|
* @param listenCallback - callback for http.Server.listen()
|
||||||
|
* @return engine.io server
|
||||||
|
*/
|
||||||
|
declare function listen(port: number, options?: AttachOptions & ServerOptions, listenCallback?: () => void): Server;
|
||||||
|
/**
|
||||||
|
* Captures upgrade requests for a http.Server.
|
||||||
|
*
|
||||||
|
* @param server
|
||||||
|
* @param options
|
||||||
|
* @return engine.io server
|
||||||
|
*/
|
||||||
|
declare function attach(server: HttpServer, options: AttachOptions & ServerOptions): Server;
|
||||||
54
node_modules/engine.io/build/engine.io.js
generated
vendored
Normal file
54
node_modules/engine.io/build/engine.io.js
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.protocol = exports.Transport = exports.Socket = exports.uServer = exports.parser = exports.transports = exports.Server = void 0;
|
||||||
|
exports.listen = listen;
|
||||||
|
exports.attach = attach;
|
||||||
|
const http_1 = require("http");
|
||||||
|
const server_1 = require("./server");
|
||||||
|
Object.defineProperty(exports, "Server", { enumerable: true, get: function () { return server_1.Server; } });
|
||||||
|
const index_1 = require("./transports/index");
|
||||||
|
exports.transports = index_1.default;
|
||||||
|
const parser = require("engine.io-parser");
|
||||||
|
exports.parser = parser;
|
||||||
|
var userver_1 = require("./userver");
|
||||||
|
Object.defineProperty(exports, "uServer", { enumerable: true, get: function () { return userver_1.uServer; } });
|
||||||
|
var socket_1 = require("./socket");
|
||||||
|
Object.defineProperty(exports, "Socket", { enumerable: true, get: function () { return socket_1.Socket; } });
|
||||||
|
var transport_1 = require("./transport");
|
||||||
|
Object.defineProperty(exports, "Transport", { enumerable: true, get: function () { return transport_1.Transport; } });
|
||||||
|
exports.protocol = parser.protocol;
|
||||||
|
/**
|
||||||
|
* Creates an http.Server exclusively used for WS upgrades, and starts listening.
|
||||||
|
*
|
||||||
|
* @param port
|
||||||
|
* @param options
|
||||||
|
* @param listenCallback - callback for http.Server.listen()
|
||||||
|
* @return engine.io server
|
||||||
|
*/
|
||||||
|
function listen(port, options, listenCallback) {
|
||||||
|
if ("function" === typeof options) {
|
||||||
|
listenCallback = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
const server = (0, http_1.createServer)(function (req, res) {
|
||||||
|
res.writeHead(501);
|
||||||
|
res.end("Not Implemented");
|
||||||
|
});
|
||||||
|
// create engine server
|
||||||
|
const engine = attach(server, options);
|
||||||
|
engine.httpServer = server;
|
||||||
|
server.listen(port, listenCallback);
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Captures upgrade requests for a http.Server.
|
||||||
|
*
|
||||||
|
* @param server
|
||||||
|
* @param options
|
||||||
|
* @return engine.io server
|
||||||
|
*/
|
||||||
|
function attach(server, options) {
|
||||||
|
const engine = new server_1.Server(options);
|
||||||
|
engine.attach(server, options);
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
88
node_modules/engine.io/build/parser-v3/index.d.ts
generated
vendored
Normal file
88
node_modules/engine.io/build/parser-v3/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* Current protocol version.
|
||||||
|
*/
|
||||||
|
export declare const protocol = 3;
|
||||||
|
/**
|
||||||
|
* Packet types.
|
||||||
|
*/
|
||||||
|
export declare const packets: {
|
||||||
|
open: number;
|
||||||
|
close: number;
|
||||||
|
ping: number;
|
||||||
|
pong: number;
|
||||||
|
message: number;
|
||||||
|
upgrade: number;
|
||||||
|
noop: number;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Encodes a packet.
|
||||||
|
*
|
||||||
|
* <packet type id> [ <data> ]
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* 5hello world
|
||||||
|
* 3
|
||||||
|
* 4
|
||||||
|
*
|
||||||
|
* Binary is encoded in an identical principle
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
export declare function encodePacket(packet: any, supportsBinary?: any, utf8encode?: any, callback?: any): any;
|
||||||
|
/**
|
||||||
|
* Encodes a packet with binary data in a base64 string
|
||||||
|
*
|
||||||
|
* @param {Object} packet, has `type` and `data`
|
||||||
|
* @return {String} base64 encoded message
|
||||||
|
*/
|
||||||
|
export declare function encodeBase64Packet(packet: any, callback: any): any;
|
||||||
|
/**
|
||||||
|
* Decodes a packet. Data also available as an ArrayBuffer if requested.
|
||||||
|
*
|
||||||
|
* @return {import('engine.io-parser').Packet} with `type` and `data` (if any)
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
export declare function decodePacket(data: any, binaryType?: any, utf8decode?: any): any;
|
||||||
|
/**
|
||||||
|
* Decodes a packet encoded in a base64 string.
|
||||||
|
*
|
||||||
|
* @param {String} base64 encoded message
|
||||||
|
* @return {Object} with `type` and `data` (if any)
|
||||||
|
*/
|
||||||
|
export declare function decodeBase64Packet(msg: any, binaryType: any): {
|
||||||
|
type: string;
|
||||||
|
data: Buffer;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Encodes multiple messages (payload).
|
||||||
|
*
|
||||||
|
* <length>:data
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* 11:hello world2:hi
|
||||||
|
*
|
||||||
|
* If any contents are binary, they will be encoded as base64 strings. Base64
|
||||||
|
* encoded strings are marked with a b before the length specifier
|
||||||
|
*
|
||||||
|
* @param {Array} packets
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
export declare function encodePayload(packets: any, supportsBinary: any, callback: any): any;
|
||||||
|
export declare function decodePayload(data: any, binaryType?: any, callback?: any): any;
|
||||||
|
/**
|
||||||
|
* Encodes multiple messages (payload) as binary.
|
||||||
|
*
|
||||||
|
* <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
|
||||||
|
* 255><data>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
|
||||||
|
*
|
||||||
|
* @param {Array} packets
|
||||||
|
* @return {Buffer} encoded payload
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
export declare function encodePayloadAsBinary(packets: any, callback: any): any;
|
||||||
|
export declare function decodePayloadAsBinary(data: any, binaryType: any, callback: any): any;
|
||||||
424
node_modules/engine.io/build/parser-v3/index.js
generated
vendored
Normal file
424
node_modules/engine.io/build/parser-v3/index.js
generated
vendored
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
"use strict";
|
||||||
|
// imported from https://github.com/socketio/engine.io-parser/tree/2.2.x
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.packets = exports.protocol = void 0;
|
||||||
|
exports.encodePacket = encodePacket;
|
||||||
|
exports.encodeBase64Packet = encodeBase64Packet;
|
||||||
|
exports.decodePacket = decodePacket;
|
||||||
|
exports.decodeBase64Packet = decodeBase64Packet;
|
||||||
|
exports.encodePayload = encodePayload;
|
||||||
|
exports.decodePayload = decodePayload;
|
||||||
|
exports.encodePayloadAsBinary = encodePayloadAsBinary;
|
||||||
|
exports.decodePayloadAsBinary = decodePayloadAsBinary;
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
*/
|
||||||
|
var utf8 = require('./utf8');
|
||||||
|
/**
|
||||||
|
* Current protocol version.
|
||||||
|
*/
|
||||||
|
exports.protocol = 3;
|
||||||
|
const hasBinary = (packets) => {
|
||||||
|
for (const packet of packets) {
|
||||||
|
if (packet.data instanceof ArrayBuffer || ArrayBuffer.isView(packet.data)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Packet types.
|
||||||
|
*/
|
||||||
|
exports.packets = {
|
||||||
|
open: 0 // non-ws
|
||||||
|
,
|
||||||
|
close: 1 // non-ws
|
||||||
|
,
|
||||||
|
ping: 2,
|
||||||
|
pong: 3,
|
||||||
|
message: 4,
|
||||||
|
upgrade: 5,
|
||||||
|
noop: 6
|
||||||
|
};
|
||||||
|
var packetslist = Object.keys(exports.packets);
|
||||||
|
/**
|
||||||
|
* Premade error packet.
|
||||||
|
*/
|
||||||
|
var err = { type: 'error', data: 'parser error' };
|
||||||
|
const EMPTY_BUFFER = Buffer.concat([]);
|
||||||
|
/**
|
||||||
|
* Encodes a packet.
|
||||||
|
*
|
||||||
|
* <packet type id> [ <data> ]
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* 5hello world
|
||||||
|
* 3
|
||||||
|
* 4
|
||||||
|
*
|
||||||
|
* Binary is encoded in an identical principle
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function encodePacket(packet, supportsBinary, utf8encode, callback) {
|
||||||
|
if (typeof supportsBinary === 'function') {
|
||||||
|
callback = supportsBinary;
|
||||||
|
supportsBinary = null;
|
||||||
|
}
|
||||||
|
if (typeof utf8encode === 'function') {
|
||||||
|
callback = utf8encode;
|
||||||
|
utf8encode = null;
|
||||||
|
}
|
||||||
|
if (Buffer.isBuffer(packet.data)) {
|
||||||
|
return encodeBuffer(packet, supportsBinary, callback);
|
||||||
|
}
|
||||||
|
else if (packet.data && (packet.data.buffer || packet.data) instanceof ArrayBuffer) {
|
||||||
|
return encodeBuffer({ type: packet.type, data: arrayBufferToBuffer(packet.data) }, supportsBinary, callback);
|
||||||
|
}
|
||||||
|
// Sending data as a utf-8 string
|
||||||
|
var encoded = exports.packets[packet.type];
|
||||||
|
// data fragment is optional
|
||||||
|
if (undefined !== packet.data) {
|
||||||
|
encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data);
|
||||||
|
}
|
||||||
|
return callback('' + encoded);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Encode Buffer data
|
||||||
|
*/
|
||||||
|
function encodeBuffer(packet, supportsBinary, callback) {
|
||||||
|
if (!supportsBinary) {
|
||||||
|
return encodeBase64Packet(packet, callback);
|
||||||
|
}
|
||||||
|
var data = packet.data;
|
||||||
|
var typeBuffer = Buffer.allocUnsafe(1);
|
||||||
|
typeBuffer[0] = exports.packets[packet.type];
|
||||||
|
return callback(Buffer.concat([typeBuffer, data]));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Encodes a packet with binary data in a base64 string
|
||||||
|
*
|
||||||
|
* @param {Object} packet, has `type` and `data`
|
||||||
|
* @return {String} base64 encoded message
|
||||||
|
*/
|
||||||
|
function encodeBase64Packet(packet, callback) {
|
||||||
|
var data = Buffer.isBuffer(packet.data) ? packet.data : arrayBufferToBuffer(packet.data);
|
||||||
|
var message = 'b' + exports.packets[packet.type];
|
||||||
|
message += data.toString('base64');
|
||||||
|
return callback(message);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
/**
|
||||||
|
* Decodes a packet. Data also available as an ArrayBuffer if requested.
|
||||||
|
*
|
||||||
|
* @return {import('engine.io-parser').Packet} with `type` and `data` (if any)
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function decodePacket(data, binaryType, utf8decode) {
|
||||||
|
if (data === undefined) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
let type;
|
||||||
|
// String data
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
type = data.charAt(0);
|
||||||
|
if (type === 'b') {
|
||||||
|
return decodeBase64Packet(data.slice(1), binaryType);
|
||||||
|
}
|
||||||
|
if (utf8decode) {
|
||||||
|
data = tryDecode(data);
|
||||||
|
if (data === false) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @ts-expect-error
|
||||||
|
if (Number(type) != type || !packetslist[type]) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (data.length > 1) {
|
||||||
|
return { type: packetslist[type], data: data.slice(1) };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { type: packetslist[type] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Binary data
|
||||||
|
if (binaryType === 'arraybuffer') {
|
||||||
|
// wrap Buffer/ArrayBuffer data into an Uint8Array
|
||||||
|
var intArray = new Uint8Array(data);
|
||||||
|
type = intArray[0];
|
||||||
|
return { type: packetslist[type], data: intArray.buffer.slice(1) };
|
||||||
|
}
|
||||||
|
if (data instanceof ArrayBuffer) {
|
||||||
|
data = arrayBufferToBuffer(data);
|
||||||
|
}
|
||||||
|
type = data[0];
|
||||||
|
return { type: packetslist[type], data: data.slice(1) };
|
||||||
|
}
|
||||||
|
;
|
||||||
|
function tryDecode(data) {
|
||||||
|
try {
|
||||||
|
data = utf8.decode(data, { strict: false });
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Decodes a packet encoded in a base64 string.
|
||||||
|
*
|
||||||
|
* @param {String} base64 encoded message
|
||||||
|
* @return {Object} with `type` and `data` (if any)
|
||||||
|
*/
|
||||||
|
function decodeBase64Packet(msg, binaryType) {
|
||||||
|
var type = packetslist[msg.charAt(0)];
|
||||||
|
var data = Buffer.from(msg.slice(1), 'base64');
|
||||||
|
if (binaryType === 'arraybuffer') {
|
||||||
|
var abv = new Uint8Array(data.length);
|
||||||
|
for (var i = 0; i < abv.length; i++) {
|
||||||
|
abv[i] = data[i];
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
data = abv.buffer;
|
||||||
|
}
|
||||||
|
return { type: type, data: data };
|
||||||
|
}
|
||||||
|
;
|
||||||
|
/**
|
||||||
|
* Encodes multiple messages (payload).
|
||||||
|
*
|
||||||
|
* <length>:data
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* 11:hello world2:hi
|
||||||
|
*
|
||||||
|
* If any contents are binary, they will be encoded as base64 strings. Base64
|
||||||
|
* encoded strings are marked with a b before the length specifier
|
||||||
|
*
|
||||||
|
* @param {Array} packets
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function encodePayload(packets, supportsBinary, callback) {
|
||||||
|
if (typeof supportsBinary === 'function') {
|
||||||
|
callback = supportsBinary;
|
||||||
|
supportsBinary = null;
|
||||||
|
}
|
||||||
|
if (supportsBinary && hasBinary(packets)) {
|
||||||
|
return encodePayloadAsBinary(packets, callback);
|
||||||
|
}
|
||||||
|
if (!packets.length) {
|
||||||
|
return callback('0:');
|
||||||
|
}
|
||||||
|
function encodeOne(packet, doneCallback) {
|
||||||
|
encodePacket(packet, supportsBinary, false, function (message) {
|
||||||
|
doneCallback(null, setLengthHeader(message));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
map(packets, encodeOne, function (err, results) {
|
||||||
|
return callback(results.join(''));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
;
|
||||||
|
function setLengthHeader(message) {
|
||||||
|
return message.length + ':' + message;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Async array map using after
|
||||||
|
*/
|
||||||
|
function map(ary, each, done) {
|
||||||
|
const results = new Array(ary.length);
|
||||||
|
let count = 0;
|
||||||
|
for (let i = 0; i < ary.length; i++) {
|
||||||
|
each(ary[i], (error, msg) => {
|
||||||
|
results[i] = msg;
|
||||||
|
if (++count === ary.length) {
|
||||||
|
done(null, results);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Decodes data when a payload is maybe expected. Possible binary contents are
|
||||||
|
* decoded from their base64 representation
|
||||||
|
*
|
||||||
|
* @param {String} data, callback method
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
function decodePayload(data, binaryType, callback) {
|
||||||
|
if (typeof data !== 'string') {
|
||||||
|
return decodePayloadAsBinary(data, binaryType, callback);
|
||||||
|
}
|
||||||
|
if (typeof binaryType === 'function') {
|
||||||
|
callback = binaryType;
|
||||||
|
binaryType = null;
|
||||||
|
}
|
||||||
|
if (data === '') {
|
||||||
|
// parser error - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
var length = '', n, msg, packet;
|
||||||
|
for (var i = 0, l = data.length; i < l; i++) {
|
||||||
|
var chr = data.charAt(i);
|
||||||
|
if (chr !== ':') {
|
||||||
|
length += chr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
if (length === '' || (length != (n = Number(length)))) {
|
||||||
|
// parser error - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
msg = data.slice(i + 1, i + 1 + n);
|
||||||
|
if (length != msg.length) {
|
||||||
|
// parser error - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
if (msg.length) {
|
||||||
|
packet = decodePacket(msg, binaryType, false);
|
||||||
|
if (err.type === packet.type && err.data === packet.data) {
|
||||||
|
// parser error in individual packet - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
var more = callback(packet, i + n, l);
|
||||||
|
if (false === more)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// advance cursor
|
||||||
|
i += n;
|
||||||
|
length = '';
|
||||||
|
}
|
||||||
|
if (length !== '') {
|
||||||
|
// parser error - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Converts a buffer to a utf8.js encoded string
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function bufferToString(buffer) {
|
||||||
|
var str = '';
|
||||||
|
for (var i = 0, l = buffer.length; i < l; i++) {
|
||||||
|
str += String.fromCharCode(buffer[i]);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Converts a utf8.js encoded string to a buffer
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function stringToBuffer(string) {
|
||||||
|
var buf = Buffer.allocUnsafe(string.length);
|
||||||
|
for (var i = 0, l = string.length; i < l; i++) {
|
||||||
|
buf.writeUInt8(string.charCodeAt(i), i);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Converts an ArrayBuffer to a Buffer
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function arrayBufferToBuffer(data) {
|
||||||
|
// data is either an ArrayBuffer or ArrayBufferView.
|
||||||
|
var length = data.byteLength || data.length;
|
||||||
|
var offset = data.byteOffset || 0;
|
||||||
|
return Buffer.from(data.buffer || data, offset, length);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Encodes multiple messages (payload) as binary.
|
||||||
|
*
|
||||||
|
* <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
|
||||||
|
* 255><data>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
|
||||||
|
*
|
||||||
|
* @param {Array} packets
|
||||||
|
* @return {Buffer} encoded payload
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function encodePayloadAsBinary(packets, callback) {
|
||||||
|
if (!packets.length) {
|
||||||
|
return callback(EMPTY_BUFFER);
|
||||||
|
}
|
||||||
|
map(packets, encodeOneBinaryPacket, function (err, results) {
|
||||||
|
return callback(Buffer.concat(results));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
;
|
||||||
|
function encodeOneBinaryPacket(p, doneCallback) {
|
||||||
|
function onBinaryPacketEncode(packet) {
|
||||||
|
var encodingLength = '' + packet.length;
|
||||||
|
var sizeBuffer;
|
||||||
|
if (typeof packet === 'string') {
|
||||||
|
sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
|
||||||
|
sizeBuffer[0] = 0; // is a string (not true binary = 0)
|
||||||
|
for (var i = 0; i < encodingLength.length; i++) {
|
||||||
|
sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
|
||||||
|
}
|
||||||
|
sizeBuffer[sizeBuffer.length - 1] = 255;
|
||||||
|
return doneCallback(null, Buffer.concat([sizeBuffer, stringToBuffer(packet)]));
|
||||||
|
}
|
||||||
|
sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
|
||||||
|
sizeBuffer[0] = 1; // is binary (true binary = 1)
|
||||||
|
for (var i = 0; i < encodingLength.length; i++) {
|
||||||
|
sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
|
||||||
|
}
|
||||||
|
sizeBuffer[sizeBuffer.length - 1] = 255;
|
||||||
|
doneCallback(null, Buffer.concat([sizeBuffer, packet]));
|
||||||
|
}
|
||||||
|
encodePacket(p, true, true, onBinaryPacketEncode);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Decodes data when a payload is maybe expected. Strings are decoded by
|
||||||
|
* interpreting each byte as a key code for entries marked to start with 0. See
|
||||||
|
* description of encodePayloadAsBinary
|
||||||
|
|
||||||
|
* @param {Buffer} data, callback method
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
function decodePayloadAsBinary(data, binaryType, callback) {
|
||||||
|
if (typeof binaryType === 'function') {
|
||||||
|
callback = binaryType;
|
||||||
|
binaryType = null;
|
||||||
|
}
|
||||||
|
var bufferTail = data;
|
||||||
|
var buffers = [];
|
||||||
|
var i;
|
||||||
|
while (bufferTail.length > 0) {
|
||||||
|
var strLen = '';
|
||||||
|
var isString = bufferTail[0] === 0;
|
||||||
|
for (i = 1;; i++) {
|
||||||
|
if (bufferTail[i] === 255)
|
||||||
|
break;
|
||||||
|
// 310 = char length of Number.MAX_VALUE
|
||||||
|
if (strLen.length > 310) {
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
strLen += '' + bufferTail[i];
|
||||||
|
}
|
||||||
|
bufferTail = bufferTail.slice(strLen.length + 1);
|
||||||
|
var msgLength = parseInt(strLen, 10);
|
||||||
|
var msg = bufferTail.slice(1, msgLength + 1);
|
||||||
|
if (isString)
|
||||||
|
msg = bufferToString(msg);
|
||||||
|
buffers.push(msg);
|
||||||
|
bufferTail = bufferTail.slice(msgLength + 1);
|
||||||
|
}
|
||||||
|
var total = buffers.length;
|
||||||
|
for (i = 0; i < total; i++) {
|
||||||
|
var buffer = buffers[i];
|
||||||
|
callback(decodePacket(buffer, binaryType, true), i, total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
14
node_modules/engine.io/build/parser-v3/utf8.d.ts
generated
vendored
Normal file
14
node_modules/engine.io/build/parser-v3/utf8.d.ts
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*! https://mths.be/utf8js v2.1.2 by @mathias */
|
||||||
|
declare var stringFromCharCode: (...codes: number[]) => string;
|
||||||
|
declare function ucs2decode(string: any): any[];
|
||||||
|
declare function ucs2encode(array: any): string;
|
||||||
|
declare function checkScalarValue(codePoint: any, strict: any): boolean;
|
||||||
|
declare function createByte(codePoint: any, shift: any): string;
|
||||||
|
declare function encodeCodePoint(codePoint: any, strict: any): string;
|
||||||
|
declare function utf8encode(string: any, opts: any): string;
|
||||||
|
declare function readContinuationByte(): number;
|
||||||
|
declare function decodeSymbol(strict: any): any;
|
||||||
|
declare var byteArray: any;
|
||||||
|
declare var byteCount: any;
|
||||||
|
declare var byteIndex: any;
|
||||||
|
declare function utf8decode(byteString: any, opts: any): string;
|
||||||
187
node_modules/engine.io/build/parser-v3/utf8.js
generated
vendored
Normal file
187
node_modules/engine.io/build/parser-v3/utf8.js
generated
vendored
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/*! https://mths.be/utf8js v2.1.2 by @mathias */
|
||||||
|
var stringFromCharCode = String.fromCharCode;
|
||||||
|
// Taken from https://mths.be/punycode
|
||||||
|
function ucs2decode(string) {
|
||||||
|
var output = [];
|
||||||
|
var counter = 0;
|
||||||
|
var length = string.length;
|
||||||
|
var value;
|
||||||
|
var extra;
|
||||||
|
while (counter < length) {
|
||||||
|
value = string.charCodeAt(counter++);
|
||||||
|
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
|
||||||
|
// high surrogate, and there is a next character
|
||||||
|
extra = string.charCodeAt(counter++);
|
||||||
|
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
|
||||||
|
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// unmatched surrogate; only append this code unit, in case the next
|
||||||
|
// code unit is the high surrogate of a surrogate pair
|
||||||
|
output.push(value);
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
output.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
// Taken from https://mths.be/punycode
|
||||||
|
function ucs2encode(array) {
|
||||||
|
var length = array.length;
|
||||||
|
var index = -1;
|
||||||
|
var value;
|
||||||
|
var output = '';
|
||||||
|
while (++index < length) {
|
||||||
|
value = array[index];
|
||||||
|
if (value > 0xFFFF) {
|
||||||
|
value -= 0x10000;
|
||||||
|
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
|
||||||
|
value = 0xDC00 | value & 0x3FF;
|
||||||
|
}
|
||||||
|
output += stringFromCharCode(value);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
function checkScalarValue(codePoint, strict) {
|
||||||
|
if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
|
||||||
|
if (strict) {
|
||||||
|
throw Error('Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
|
||||||
|
' is not a scalar value');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
function createByte(codePoint, shift) {
|
||||||
|
return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
|
||||||
|
}
|
||||||
|
function encodeCodePoint(codePoint, strict) {
|
||||||
|
if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
|
||||||
|
return stringFromCharCode(codePoint);
|
||||||
|
}
|
||||||
|
var symbol = '';
|
||||||
|
if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
|
||||||
|
symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
|
||||||
|
}
|
||||||
|
else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
|
||||||
|
if (!checkScalarValue(codePoint, strict)) {
|
||||||
|
codePoint = 0xFFFD;
|
||||||
|
}
|
||||||
|
symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
|
||||||
|
symbol += createByte(codePoint, 6);
|
||||||
|
}
|
||||||
|
else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
|
||||||
|
symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
|
||||||
|
symbol += createByte(codePoint, 12);
|
||||||
|
symbol += createByte(codePoint, 6);
|
||||||
|
}
|
||||||
|
symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
function utf8encode(string, opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
var strict = false !== opts.strict;
|
||||||
|
var codePoints = ucs2decode(string);
|
||||||
|
var length = codePoints.length;
|
||||||
|
var index = -1;
|
||||||
|
var codePoint;
|
||||||
|
var byteString = '';
|
||||||
|
while (++index < length) {
|
||||||
|
codePoint = codePoints[index];
|
||||||
|
byteString += encodeCodePoint(codePoint, strict);
|
||||||
|
}
|
||||||
|
return byteString;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
function readContinuationByte() {
|
||||||
|
if (byteIndex >= byteCount) {
|
||||||
|
throw Error('Invalid byte index');
|
||||||
|
}
|
||||||
|
var continuationByte = byteArray[byteIndex] & 0xFF;
|
||||||
|
byteIndex++;
|
||||||
|
if ((continuationByte & 0xC0) == 0x80) {
|
||||||
|
return continuationByte & 0x3F;
|
||||||
|
}
|
||||||
|
// If we end up here, it’s not a continuation byte
|
||||||
|
throw Error('Invalid continuation byte');
|
||||||
|
}
|
||||||
|
function decodeSymbol(strict) {
|
||||||
|
var byte1;
|
||||||
|
var byte2;
|
||||||
|
var byte3;
|
||||||
|
var byte4;
|
||||||
|
var codePoint;
|
||||||
|
if (byteIndex > byteCount) {
|
||||||
|
throw Error('Invalid byte index');
|
||||||
|
}
|
||||||
|
if (byteIndex == byteCount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Read first byte
|
||||||
|
byte1 = byteArray[byteIndex] & 0xFF;
|
||||||
|
byteIndex++;
|
||||||
|
// 1-byte sequence (no continuation bytes)
|
||||||
|
if ((byte1 & 0x80) == 0) {
|
||||||
|
return byte1;
|
||||||
|
}
|
||||||
|
// 2-byte sequence
|
||||||
|
if ((byte1 & 0xE0) == 0xC0) {
|
||||||
|
byte2 = readContinuationByte();
|
||||||
|
codePoint = ((byte1 & 0x1F) << 6) | byte2;
|
||||||
|
if (codePoint >= 0x80) {
|
||||||
|
return codePoint;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw Error('Invalid continuation byte');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 3-byte sequence (may include unpaired surrogates)
|
||||||
|
if ((byte1 & 0xF0) == 0xE0) {
|
||||||
|
byte2 = readContinuationByte();
|
||||||
|
byte3 = readContinuationByte();
|
||||||
|
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
|
||||||
|
if (codePoint >= 0x0800) {
|
||||||
|
return checkScalarValue(codePoint, strict) ? codePoint : 0xFFFD;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw Error('Invalid continuation byte');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 4-byte sequence
|
||||||
|
if ((byte1 & 0xF8) == 0xF0) {
|
||||||
|
byte2 = readContinuationByte();
|
||||||
|
byte3 = readContinuationByte();
|
||||||
|
byte4 = readContinuationByte();
|
||||||
|
codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) |
|
||||||
|
(byte3 << 0x06) | byte4;
|
||||||
|
if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
|
||||||
|
return codePoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Error('Invalid UTF-8 detected');
|
||||||
|
}
|
||||||
|
var byteArray;
|
||||||
|
var byteCount;
|
||||||
|
var byteIndex;
|
||||||
|
function utf8decode(byteString, opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
var strict = false !== opts.strict;
|
||||||
|
byteArray = ucs2decode(byteString);
|
||||||
|
byteCount = byteArray.length;
|
||||||
|
byteIndex = 0;
|
||||||
|
var codePoints = [];
|
||||||
|
var tmp;
|
||||||
|
while ((tmp = decodeSymbol(strict)) !== false) {
|
||||||
|
codePoints.push(tmp);
|
||||||
|
}
|
||||||
|
return ucs2encode(codePoints);
|
||||||
|
}
|
||||||
|
module.exports = {
|
||||||
|
version: '2.1.2',
|
||||||
|
encode: utf8encode,
|
||||||
|
decode: utf8decode
|
||||||
|
};
|
||||||
272
node_modules/engine.io/build/server.d.ts
generated
vendored
Normal file
272
node_modules/engine.io/build/server.d.ts
generated
vendored
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
import { EventEmitter } from "events";
|
||||||
|
import { Socket } from "./socket";
|
||||||
|
import { type PerMessageDeflateOptions } from "ws";
|
||||||
|
import type { IncomingMessage, Server as HttpServer, ServerResponse } from "http";
|
||||||
|
import type { CorsOptions, CorsOptionsDelegate } from "cors";
|
||||||
|
import type { Duplex } from "stream";
|
||||||
|
import type { EngineRequest, Transport } from "./transport";
|
||||||
|
import type { CookieSerializeOptions } from "./contrib/types.cookie";
|
||||||
|
type TransportName = "polling" | "websocket" | "webtransport";
|
||||||
|
export type ErrorCallback = (errorCode?: (typeof Server.errors)[keyof typeof Server.errors], errorContext?: Record<string, unknown> & {
|
||||||
|
name?: string;
|
||||||
|
message?: string;
|
||||||
|
}) => void;
|
||||||
|
export interface AttachOptions {
|
||||||
|
/**
|
||||||
|
* name of the path to capture
|
||||||
|
* @default "/engine.io"
|
||||||
|
*/
|
||||||
|
path?: string;
|
||||||
|
/**
|
||||||
|
* destroy unhandled upgrade requests
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
destroyUpgrade?: boolean;
|
||||||
|
/**
|
||||||
|
* milliseconds after which unhandled requests are ended
|
||||||
|
* @default 1000
|
||||||
|
*/
|
||||||
|
destroyUpgradeTimeout?: number;
|
||||||
|
/**
|
||||||
|
* Whether we should add a trailing slash to the request path.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
addTrailingSlash?: boolean;
|
||||||
|
}
|
||||||
|
export interface ServerOptions {
|
||||||
|
/**
|
||||||
|
* how many ms without a pong packet to consider the connection closed
|
||||||
|
* @default 20000
|
||||||
|
*/
|
||||||
|
pingTimeout?: number;
|
||||||
|
/**
|
||||||
|
* how many ms before sending a new ping packet
|
||||||
|
* @default 25000
|
||||||
|
*/
|
||||||
|
pingInterval?: number;
|
||||||
|
/**
|
||||||
|
* how many ms before an uncompleted transport upgrade is cancelled
|
||||||
|
* @default 10000
|
||||||
|
*/
|
||||||
|
upgradeTimeout?: number;
|
||||||
|
/**
|
||||||
|
* how many bytes or characters a message can be, before closing the session (to avoid DoS).
|
||||||
|
* @default 1e5 (100 KB)
|
||||||
|
*/
|
||||||
|
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: IncomingMessage, fn: (err: string | null | undefined, success: boolean) => void) => void;
|
||||||
|
/**
|
||||||
|
* The low-level transports that are enabled. WebTransport is disabled by default and must be manually enabled:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* new Server({
|
||||||
|
* transports: ["polling", "websocket", "webtransport"]
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* @default ["polling", "websocket"]
|
||||||
|
*/
|
||||||
|
transports?: TransportName[];
|
||||||
|
/**
|
||||||
|
* whether to allow transport upgrades
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
allowUpgrades?: boolean;
|
||||||
|
/**
|
||||||
|
* parameters of the WebSocket permessage-deflate extension (see ws module api docs). Set to false to disable.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
perMessageDeflate?: boolean | PerMessageDeflateOptions;
|
||||||
|
/**
|
||||||
|
* parameters of the http compression for the polling transports (see zlib api docs). Set to false to disable.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
httpCompression?: boolean | object;
|
||||||
|
/**
|
||||||
|
* what WebSocket server implementation to use. Specified module must
|
||||||
|
* conform to the ws interface (see ws module api docs).
|
||||||
|
* An alternative c++ addon is also available by installing eiows module.
|
||||||
|
*
|
||||||
|
* @default `require("ws").Server`
|
||||||
|
*/
|
||||||
|
wsEngine?: any;
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
cookie?: (CookieSerializeOptions & {
|
||||||
|
name: string;
|
||||||
|
}) | boolean;
|
||||||
|
/**
|
||||||
|
* the options that will be forwarded to the cors module
|
||||||
|
*/
|
||||||
|
cors?: CorsOptions | CorsOptionsDelegate;
|
||||||
|
/**
|
||||||
|
* whether to enable compatibility with Socket.IO v2 clients
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
allowEIO3?: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* An Express-compatible middleware.
|
||||||
|
*
|
||||||
|
* Middleware functions are functions that have access to the request object (req), the response object (res), and the
|
||||||
|
* next middleware function in the application’s request-response cycle.
|
||||||
|
*
|
||||||
|
* @see https://expressjs.com/en/guide/using-middleware.html
|
||||||
|
*/
|
||||||
|
type Middleware = (req: IncomingMessage, res: ServerResponse, next: (err?: any) => void) => void;
|
||||||
|
export declare abstract class BaseServer extends EventEmitter {
|
||||||
|
opts: ServerOptions;
|
||||||
|
protected clients: Record<string, Socket>;
|
||||||
|
clientsCount: number;
|
||||||
|
protected middlewares: Middleware[];
|
||||||
|
/**
|
||||||
|
* Server constructor.
|
||||||
|
*
|
||||||
|
* @param {Object} opts - options
|
||||||
|
*/
|
||||||
|
constructor(opts?: ServerOptions);
|
||||||
|
protected abstract init(): void;
|
||||||
|
/**
|
||||||
|
* Compute the pathname of the requests that are handled by the server
|
||||||
|
* @param options
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected _computePath(options: AttachOptions): string;
|
||||||
|
/**
|
||||||
|
* Returns a list of available transports for upgrade given a certain transport.
|
||||||
|
*/
|
||||||
|
upgrades(transport: TransportName): string[];
|
||||||
|
/**
|
||||||
|
* Verifies a request.
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
* @param upgrade - whether it's an upgrade request
|
||||||
|
* @param fn
|
||||||
|
* @protected
|
||||||
|
* @return whether the request is valid
|
||||||
|
*/
|
||||||
|
protected verify(req: EngineRequest, upgrade: boolean, fn: ErrorCallback): void | boolean;
|
||||||
|
/**
|
||||||
|
* Adds a new middleware.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* import helmet from "helmet";
|
||||||
|
*
|
||||||
|
* engine.use(helmet());
|
||||||
|
*
|
||||||
|
* @param fn
|
||||||
|
*/
|
||||||
|
use(fn: any): void;
|
||||||
|
/**
|
||||||
|
* Apply the middlewares to the request.
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
* @param callback
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected _applyMiddlewares(req: IncomingMessage, res: ServerResponse, callback: (err?: any) => void): void;
|
||||||
|
/**
|
||||||
|
* Closes all clients.
|
||||||
|
*/
|
||||||
|
close(): this;
|
||||||
|
protected abstract cleanup(): any;
|
||||||
|
/**
|
||||||
|
* generate a socket id.
|
||||||
|
* Overwrite this method to generate your custom socket id
|
||||||
|
*
|
||||||
|
* @param {IncomingMessage} req - the request object
|
||||||
|
*/
|
||||||
|
generateId(req: IncomingMessage): string | PromiseLike<string>;
|
||||||
|
/**
|
||||||
|
* Handshakes a new client.
|
||||||
|
*
|
||||||
|
* @param {String} transportName
|
||||||
|
* @param {Object} req - the request object
|
||||||
|
* @param {Function} closeConnection
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected handshake(transportName: TransportName, req: EngineRequest, closeConnection: ErrorCallback): Promise<any>;
|
||||||
|
onWebTransportSession(session: any): Promise<any>;
|
||||||
|
protected abstract createTransport(transportName: TransportName, req: EngineRequest): any;
|
||||||
|
/**
|
||||||
|
* Protocol errors mappings.
|
||||||
|
*/
|
||||||
|
static errors: {
|
||||||
|
readonly UNKNOWN_TRANSPORT: 0;
|
||||||
|
readonly UNKNOWN_SID: 1;
|
||||||
|
readonly BAD_HANDSHAKE_METHOD: 2;
|
||||||
|
readonly BAD_REQUEST: 3;
|
||||||
|
readonly FORBIDDEN: 4;
|
||||||
|
readonly UNSUPPORTED_PROTOCOL_VERSION: 5;
|
||||||
|
};
|
||||||
|
static errorMessages: {
|
||||||
|
readonly 0: "Transport unknown";
|
||||||
|
readonly 1: "Session ID unknown";
|
||||||
|
readonly 2: "Bad handshake method";
|
||||||
|
readonly 3: "Bad request";
|
||||||
|
readonly 4: "Forbidden";
|
||||||
|
readonly 5: "Unsupported protocol version";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* An Engine.IO server based on Node.js built-in HTTP server and the `ws` package for WebSocket connections.
|
||||||
|
*/
|
||||||
|
export declare class Server extends BaseServer {
|
||||||
|
httpServer?: HttpServer;
|
||||||
|
private ws;
|
||||||
|
/**
|
||||||
|
* Initialize websocket server
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected init(): void;
|
||||||
|
protected cleanup(): void;
|
||||||
|
/**
|
||||||
|
* Prepares a request by processing the query string.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private prepare;
|
||||||
|
protected createTransport(transportName: TransportName, req: IncomingMessage): Transport;
|
||||||
|
/**
|
||||||
|
* Handles an Engine.IO HTTP request.
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
* @param {ServerResponse} res
|
||||||
|
*/
|
||||||
|
handleRequest(req: EngineRequest, res: ServerResponse): void;
|
||||||
|
/**
|
||||||
|
* Handles an Engine.IO HTTP Upgrade.
|
||||||
|
*/
|
||||||
|
handleUpgrade(req: EngineRequest, socket: Duplex, upgradeHead: Buffer): void;
|
||||||
|
/**
|
||||||
|
* Called upon a ws.io connection.
|
||||||
|
* @param req
|
||||||
|
* @param socket
|
||||||
|
* @param websocket
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private onWebSocket;
|
||||||
|
/**
|
||||||
|
* Captures upgrade requests for a http.Server.
|
||||||
|
*
|
||||||
|
* @param {http.Server} server
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
attach(server: HttpServer, options?: AttachOptions): void;
|
||||||
|
}
|
||||||
|
export {};
|
||||||
787
node_modules/engine.io/build/server.js
generated
vendored
Normal file
787
node_modules/engine.io/build/server.js
generated
vendored
Normal file
@ -0,0 +1,787 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Server = exports.BaseServer = void 0;
|
||||||
|
const base64id = require("base64id");
|
||||||
|
const transports_1 = require("./transports");
|
||||||
|
const events_1 = require("events");
|
||||||
|
const socket_1 = require("./socket");
|
||||||
|
const debug_1 = require("debug");
|
||||||
|
const cookie_1 = require("cookie");
|
||||||
|
const ws_1 = require("ws");
|
||||||
|
const webtransport_1 = require("./transports/webtransport");
|
||||||
|
const engine_io_parser_1 = require("engine.io-parser");
|
||||||
|
const debug = (0, debug_1.default)("engine");
|
||||||
|
const kResponseHeaders = Symbol("responseHeaders");
|
||||||
|
function parseSessionId(data) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(data);
|
||||||
|
if (typeof parsed.sid === "string") {
|
||||||
|
return parsed.sid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) { }
|
||||||
|
}
|
||||||
|
class BaseServer extends events_1.EventEmitter {
|
||||||
|
/**
|
||||||
|
* Server constructor.
|
||||||
|
*
|
||||||
|
* @param {Object} opts - options
|
||||||
|
*/
|
||||||
|
constructor(opts = {}) {
|
||||||
|
super();
|
||||||
|
this.middlewares = [];
|
||||||
|
this.clients = {};
|
||||||
|
this.clientsCount = 0;
|
||||||
|
this.opts = Object.assign({
|
||||||
|
wsEngine: ws_1.Server,
|
||||||
|
pingTimeout: 20000,
|
||||||
|
pingInterval: 25000,
|
||||||
|
upgradeTimeout: 10000,
|
||||||
|
maxHttpBufferSize: 1e6,
|
||||||
|
transports: ["polling", "websocket"], // WebTransport is disabled by default
|
||||||
|
allowUpgrades: true,
|
||||||
|
httpCompression: {
|
||||||
|
threshold: 1024,
|
||||||
|
},
|
||||||
|
cors: false,
|
||||||
|
allowEIO3: false,
|
||||||
|
}, opts);
|
||||||
|
if (opts.cookie) {
|
||||||
|
this.opts.cookie = Object.assign({
|
||||||
|
name: "io",
|
||||||
|
path: "/",
|
||||||
|
// @ts-ignore
|
||||||
|
httpOnly: opts.cookie.path !== false,
|
||||||
|
sameSite: "lax",
|
||||||
|
}, opts.cookie);
|
||||||
|
}
|
||||||
|
if (this.opts.cors) {
|
||||||
|
this.use(require("cors")(this.opts.cors));
|
||||||
|
}
|
||||||
|
if (opts.perMessageDeflate) {
|
||||||
|
this.opts.perMessageDeflate = Object.assign({
|
||||||
|
threshold: 1024,
|
||||||
|
}, opts.perMessageDeflate);
|
||||||
|
}
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Compute the pathname of the requests that are handled by the server
|
||||||
|
* @param options
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_computePath(options) {
|
||||||
|
let path = (options.path || "/engine.io").replace(/\/$/, "");
|
||||||
|
if (options.addTrailingSlash !== false) {
|
||||||
|
// normalize path
|
||||||
|
path += "/";
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns a list of available transports for upgrade given a certain transport.
|
||||||
|
*/
|
||||||
|
upgrades(transport) {
|
||||||
|
if (!this.opts.allowUpgrades)
|
||||||
|
return [];
|
||||||
|
return transports_1.default[transport].upgradesTo || [];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Verifies a request.
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
* @param upgrade - whether it's an upgrade request
|
||||||
|
* @param fn
|
||||||
|
* @protected
|
||||||
|
* @return whether the request is valid
|
||||||
|
*/
|
||||||
|
verify(req, upgrade, fn) {
|
||||||
|
// transport check
|
||||||
|
const transport = req._query.transport;
|
||||||
|
// WebTransport does not go through the verify() method, see the onWebTransportSession() method
|
||||||
|
if (!~this.opts.transports.indexOf(transport) ||
|
||||||
|
transport === "webtransport") {
|
||||||
|
debug('unknown transport "%s"', transport);
|
||||||
|
return fn(Server.errors.UNKNOWN_TRANSPORT, { transport });
|
||||||
|
}
|
||||||
|
// 'Origin' header check
|
||||||
|
const isOriginInvalid = checkInvalidHeaderChar(req.headers.origin);
|
||||||
|
if (isOriginInvalid) {
|
||||||
|
const origin = req.headers.origin;
|
||||||
|
req.headers.origin = null;
|
||||||
|
debug("origin header invalid");
|
||||||
|
return fn(Server.errors.BAD_REQUEST, {
|
||||||
|
name: "INVALID_ORIGIN",
|
||||||
|
origin,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// sid check
|
||||||
|
const sid = req._query.sid;
|
||||||
|
if (sid) {
|
||||||
|
if (!this.clients.hasOwnProperty(sid)) {
|
||||||
|
debug('unknown sid "%s"', sid);
|
||||||
|
return fn(Server.errors.UNKNOWN_SID, {
|
||||||
|
sid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const previousTransport = this.clients[sid].transport.name;
|
||||||
|
if (!upgrade && previousTransport !== transport) {
|
||||||
|
debug("bad request: unexpected transport without upgrade");
|
||||||
|
return fn(Server.errors.BAD_REQUEST, {
|
||||||
|
name: "TRANSPORT_MISMATCH",
|
||||||
|
transport,
|
||||||
|
previousTransport,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// handshake is GET only
|
||||||
|
if ("GET" !== req.method) {
|
||||||
|
return fn(Server.errors.BAD_HANDSHAKE_METHOD, {
|
||||||
|
method: req.method,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (transport === "websocket" && !upgrade) {
|
||||||
|
debug("invalid transport upgrade");
|
||||||
|
return fn(Server.errors.BAD_REQUEST, {
|
||||||
|
name: "TRANSPORT_HANDSHAKE_ERROR",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!this.opts.allowRequest)
|
||||||
|
return fn();
|
||||||
|
return this.opts.allowRequest(req, (message, success) => {
|
||||||
|
if (!success) {
|
||||||
|
return fn(Server.errors.FORBIDDEN, {
|
||||||
|
message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds a new middleware.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* import helmet from "helmet";
|
||||||
|
*
|
||||||
|
* engine.use(helmet());
|
||||||
|
*
|
||||||
|
* @param fn
|
||||||
|
*/
|
||||||
|
use(fn) {
|
||||||
|
this.middlewares.push(fn);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Apply the middlewares to the request.
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
* @param callback
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_applyMiddlewares(req, res, callback) {
|
||||||
|
if (this.middlewares.length === 0) {
|
||||||
|
debug("no middleware to apply, skipping");
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
const apply = (i) => {
|
||||||
|
debug("applying middleware n°%d", i + 1);
|
||||||
|
this.middlewares[i](req, res, (err) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
if (i + 1 < this.middlewares.length) {
|
||||||
|
apply(i + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
apply(0);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Closes all clients.
|
||||||
|
*/
|
||||||
|
close() {
|
||||||
|
debug("closing all open clients");
|
||||||
|
for (let i in this.clients) {
|
||||||
|
if (this.clients.hasOwnProperty(i)) {
|
||||||
|
this.clients[i].close(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.cleanup();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* generate a socket id.
|
||||||
|
* Overwrite this method to generate your custom socket id
|
||||||
|
*
|
||||||
|
* @param {IncomingMessage} req - the request object
|
||||||
|
*/
|
||||||
|
generateId(req) {
|
||||||
|
return base64id.generateId();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handshakes a new client.
|
||||||
|
*
|
||||||
|
* @param {String} transportName
|
||||||
|
* @param {Object} req - the request object
|
||||||
|
* @param {Function} closeConnection
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
async handshake(transportName, req, closeConnection) {
|
||||||
|
const protocol = req._query.EIO === "4" ? 4 : 3; // 3rd revision by default
|
||||||
|
if (protocol === 3 && !this.opts.allowEIO3) {
|
||||||
|
debug("unsupported protocol version");
|
||||||
|
this.emit("connection_error", {
|
||||||
|
req,
|
||||||
|
code: Server.errors.UNSUPPORTED_PROTOCOL_VERSION,
|
||||||
|
message: Server.errorMessages[Server.errors.UNSUPPORTED_PROTOCOL_VERSION],
|
||||||
|
context: {
|
||||||
|
protocol,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
closeConnection(Server.errors.UNSUPPORTED_PROTOCOL_VERSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let id;
|
||||||
|
try {
|
||||||
|
id = await this.generateId(req);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
debug("error while generating an id");
|
||||||
|
this.emit("connection_error", {
|
||||||
|
req,
|
||||||
|
code: Server.errors.BAD_REQUEST,
|
||||||
|
message: Server.errorMessages[Server.errors.BAD_REQUEST],
|
||||||
|
context: {
|
||||||
|
name: "ID_GENERATION_ERROR",
|
||||||
|
error: e,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
closeConnection(Server.errors.BAD_REQUEST);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug('handshaking client "%s"', id);
|
||||||
|
try {
|
||||||
|
var transport = this.createTransport(transportName, req);
|
||||||
|
if ("polling" === transportName) {
|
||||||
|
transport.maxHttpBufferSize = this.opts.maxHttpBufferSize;
|
||||||
|
transport.httpCompression = this.opts.httpCompression;
|
||||||
|
}
|
||||||
|
else if ("websocket" === transportName) {
|
||||||
|
transport.perMessageDeflate = this.opts.perMessageDeflate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
debug('error handshaking to transport "%s"', transportName);
|
||||||
|
this.emit("connection_error", {
|
||||||
|
req,
|
||||||
|
code: Server.errors.BAD_REQUEST,
|
||||||
|
message: Server.errorMessages[Server.errors.BAD_REQUEST],
|
||||||
|
context: {
|
||||||
|
name: "TRANSPORT_HANDSHAKE_ERROR",
|
||||||
|
error: e,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
closeConnection(Server.errors.BAD_REQUEST);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const socket = new socket_1.Socket(id, this, transport, req, protocol);
|
||||||
|
transport.on("headers", (headers, req) => {
|
||||||
|
const isInitialRequest = !req._query.sid;
|
||||||
|
if (isInitialRequest) {
|
||||||
|
if (this.opts.cookie) {
|
||||||
|
headers["Set-Cookie"] = [
|
||||||
|
// @ts-ignore
|
||||||
|
(0, cookie_1.serialize)(this.opts.cookie.name, id, this.opts.cookie),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
this.emit("initial_headers", headers, req);
|
||||||
|
}
|
||||||
|
this.emit("headers", headers, req);
|
||||||
|
});
|
||||||
|
transport.onRequest(req);
|
||||||
|
this.clients[id] = socket;
|
||||||
|
this.clientsCount++;
|
||||||
|
socket.once("close", () => {
|
||||||
|
delete this.clients[id];
|
||||||
|
this.clientsCount--;
|
||||||
|
});
|
||||||
|
this.emit("connection", socket);
|
||||||
|
return transport;
|
||||||
|
}
|
||||||
|
async onWebTransportSession(session) {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
debug("the client failed to establish a bidirectional stream in the given period");
|
||||||
|
session.close();
|
||||||
|
}, this.opts.upgradeTimeout);
|
||||||
|
const streamReader = session.incomingBidirectionalStreams.getReader();
|
||||||
|
const result = await streamReader.read();
|
||||||
|
if (result.done) {
|
||||||
|
debug("session is closed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const stream = result.value;
|
||||||
|
const transformStream = (0, engine_io_parser_1.createPacketDecoderStream)(this.opts.maxHttpBufferSize, "nodebuffer");
|
||||||
|
const reader = stream.readable.pipeThrough(transformStream).getReader();
|
||||||
|
// reading the first packet of the stream
|
||||||
|
const { value, done } = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
debug("stream is closed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearTimeout(timeout);
|
||||||
|
if (value.type !== "open") {
|
||||||
|
debug("invalid WebTransport handshake");
|
||||||
|
return session.close();
|
||||||
|
}
|
||||||
|
if (value.data === undefined) {
|
||||||
|
const transport = new webtransport_1.WebTransport(session, stream, reader);
|
||||||
|
// note: we cannot use "this.generateId()", because there is no "req" argument
|
||||||
|
const id = base64id.generateId();
|
||||||
|
debug('handshaking client "%s" (WebTransport)', id);
|
||||||
|
const socket = new socket_1.Socket(id, this, transport, null, 4);
|
||||||
|
this.clients[id] = socket;
|
||||||
|
this.clientsCount++;
|
||||||
|
socket.once("close", () => {
|
||||||
|
delete this.clients[id];
|
||||||
|
this.clientsCount--;
|
||||||
|
});
|
||||||
|
this.emit("connection", socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const sid = parseSessionId(value.data);
|
||||||
|
if (!sid) {
|
||||||
|
debug("invalid WebTransport handshake");
|
||||||
|
return session.close();
|
||||||
|
}
|
||||||
|
const client = this.clients[sid];
|
||||||
|
if (!client) {
|
||||||
|
debug("upgrade attempt for closed client");
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
else if (client.upgrading) {
|
||||||
|
debug("transport has already been trying to upgrade");
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
else if (client.upgraded) {
|
||||||
|
debug("transport had already been upgraded");
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("upgrading existing transport");
|
||||||
|
const transport = new webtransport_1.WebTransport(session, stream, reader);
|
||||||
|
client._maybeUpgrade(transport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.BaseServer = BaseServer;
|
||||||
|
/**
|
||||||
|
* Protocol errors mappings.
|
||||||
|
*/
|
||||||
|
BaseServer.errors = {
|
||||||
|
UNKNOWN_TRANSPORT: 0,
|
||||||
|
UNKNOWN_SID: 1,
|
||||||
|
BAD_HANDSHAKE_METHOD: 2,
|
||||||
|
BAD_REQUEST: 3,
|
||||||
|
FORBIDDEN: 4,
|
||||||
|
UNSUPPORTED_PROTOCOL_VERSION: 5,
|
||||||
|
};
|
||||||
|
BaseServer.errorMessages = {
|
||||||
|
0: "Transport unknown",
|
||||||
|
1: "Session ID unknown",
|
||||||
|
2: "Bad handshake method",
|
||||||
|
3: "Bad request",
|
||||||
|
4: "Forbidden",
|
||||||
|
5: "Unsupported protocol version",
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Exposes a subset of the http.ServerResponse interface, in order to be able to apply the middlewares to an upgrade
|
||||||
|
* request.
|
||||||
|
*
|
||||||
|
* @see https://nodejs.org/api/http.html#class-httpserverresponse
|
||||||
|
*/
|
||||||
|
class WebSocketResponse {
|
||||||
|
constructor(req, socket) {
|
||||||
|
this.req = req;
|
||||||
|
this.socket = socket;
|
||||||
|
// temporarily store the response headers on the req object (see the "headers" event)
|
||||||
|
req[kResponseHeaders] = {};
|
||||||
|
}
|
||||||
|
setHeader(name, value) {
|
||||||
|
this.req[kResponseHeaders][name] = value;
|
||||||
|
}
|
||||||
|
getHeader(name) {
|
||||||
|
return this.req[kResponseHeaders][name];
|
||||||
|
}
|
||||||
|
removeHeader(name) {
|
||||||
|
delete this.req[kResponseHeaders][name];
|
||||||
|
}
|
||||||
|
write() { }
|
||||||
|
writeHead() { }
|
||||||
|
end() {
|
||||||
|
// we could return a proper error code, but the WebSocket client will emit an "error" event anyway.
|
||||||
|
this.socket.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* An Engine.IO server based on Node.js built-in HTTP server and the `ws` package for WebSocket connections.
|
||||||
|
*/
|
||||||
|
class Server extends BaseServer {
|
||||||
|
/**
|
||||||
|
* Initialize websocket server
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
if (!~this.opts.transports.indexOf("websocket"))
|
||||||
|
return;
|
||||||
|
if (this.ws)
|
||||||
|
this.ws.close();
|
||||||
|
this.ws = new this.opts.wsEngine({
|
||||||
|
noServer: true,
|
||||||
|
clientTracking: false,
|
||||||
|
perMessageDeflate: this.opts.perMessageDeflate,
|
||||||
|
maxPayload: this.opts.maxHttpBufferSize,
|
||||||
|
});
|
||||||
|
if (typeof this.ws.on === "function") {
|
||||||
|
this.ws.on("headers", (headersArray, req) => {
|
||||||
|
// note: 'ws' uses an array of headers, while Engine.IO uses an object (response.writeHead() accepts both formats)
|
||||||
|
// we could also try to parse the array and then sync the values, but that will be error-prone
|
||||||
|
const additionalHeaders = req[kResponseHeaders] || {};
|
||||||
|
delete req[kResponseHeaders];
|
||||||
|
const isInitialRequest = !req._query.sid;
|
||||||
|
if (isInitialRequest) {
|
||||||
|
this.emit("initial_headers", additionalHeaders, req);
|
||||||
|
}
|
||||||
|
this.emit("headers", additionalHeaders, req);
|
||||||
|
debug("writing headers: %j", additionalHeaders);
|
||||||
|
Object.keys(additionalHeaders).forEach((key) => {
|
||||||
|
headersArray.push(`${key}: ${additionalHeaders[key]}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanup() {
|
||||||
|
if (this.ws) {
|
||||||
|
debug("closing webSocketServer");
|
||||||
|
this.ws.close();
|
||||||
|
// don't delete this.ws because it can be used again if the http server starts listening again
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Prepares a request by processing the query string.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
prepare(req) {
|
||||||
|
// try to leverage pre-existing `req._query` (e.g: from connect)
|
||||||
|
if (!req._query) {
|
||||||
|
const url = new URL(req.url, "https://socket.io");
|
||||||
|
req._query = Object.fromEntries(url.searchParams.entries());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createTransport(transportName, req) {
|
||||||
|
// @ts-expect-error 'polling' is a plain function used as constructor
|
||||||
|
return new transports_1.default[transportName](req);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handles an Engine.IO HTTP request.
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
* @param {ServerResponse} res
|
||||||
|
*/
|
||||||
|
handleRequest(req, res) {
|
||||||
|
debug('handling "%s" http request "%s"', req.method, req.url);
|
||||||
|
this.prepare(req);
|
||||||
|
req.res = res;
|
||||||
|
const callback = (errorCode, errorContext) => {
|
||||||
|
if (errorCode !== undefined) {
|
||||||
|
this.emit("connection_error", {
|
||||||
|
req,
|
||||||
|
code: errorCode,
|
||||||
|
message: Server.errorMessages[errorCode],
|
||||||
|
context: errorContext,
|
||||||
|
});
|
||||||
|
abortRequest(res, errorCode, errorContext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (req._query.sid) {
|
||||||
|
debug("setting new request for existing client");
|
||||||
|
this.clients[req._query.sid].transport.onRequest(req);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const closeConnection = (errorCode, errorContext) => abortRequest(res, errorCode, errorContext);
|
||||||
|
this.handshake(req._query.transport, req, closeConnection);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this._applyMiddlewares(req, res, (err) => {
|
||||||
|
if (err) {
|
||||||
|
callback(Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.verify(req, false, callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handles an Engine.IO HTTP Upgrade.
|
||||||
|
*/
|
||||||
|
handleUpgrade(req, socket, upgradeHead) {
|
||||||
|
this.prepare(req);
|
||||||
|
const res = new WebSocketResponse(req, socket);
|
||||||
|
const callback = (errorCode, errorContext) => {
|
||||||
|
if (errorCode !== undefined) {
|
||||||
|
this.emit("connection_error", {
|
||||||
|
req,
|
||||||
|
code: errorCode,
|
||||||
|
message: Server.errorMessages[errorCode],
|
||||||
|
context: errorContext,
|
||||||
|
});
|
||||||
|
abortUpgrade(socket, errorCode, errorContext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const head = Buffer.from(upgradeHead);
|
||||||
|
upgradeHead = null;
|
||||||
|
// some middlewares (like express-session) wait for the writeHead() call to flush their headers
|
||||||
|
// see https://github.com/expressjs/session/blob/1010fadc2f071ddf2add94235d72224cf65159c6/index.js#L220-L244
|
||||||
|
res.writeHead();
|
||||||
|
// delegate to ws
|
||||||
|
this.ws.handleUpgrade(req, socket, head, (websocket) => {
|
||||||
|
this.onWebSocket(req, socket, websocket);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this._applyMiddlewares(req, res, (err) => {
|
||||||
|
if (err) {
|
||||||
|
callback(Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.verify(req, true, callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called upon a ws.io connection.
|
||||||
|
* @param req
|
||||||
|
* @param socket
|
||||||
|
* @param websocket
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onWebSocket(req, socket, websocket) {
|
||||||
|
websocket.on("error", onUpgradeError);
|
||||||
|
if (transports_1.default[req._query.transport] !== undefined &&
|
||||||
|
!transports_1.default[req._query.transport].prototype.handlesUpgrades) {
|
||||||
|
debug("transport doesnt handle upgraded requests");
|
||||||
|
websocket.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// get client id
|
||||||
|
const id = req._query.sid;
|
||||||
|
// keep a reference to the ws.Socket
|
||||||
|
req.websocket = websocket;
|
||||||
|
if (id) {
|
||||||
|
const client = this.clients[id];
|
||||||
|
if (!client) {
|
||||||
|
debug("upgrade attempt for closed client");
|
||||||
|
websocket.close();
|
||||||
|
}
|
||||||
|
else if (client.upgrading) {
|
||||||
|
debug("transport has already been trying to upgrade");
|
||||||
|
websocket.close();
|
||||||
|
}
|
||||||
|
else if (client.upgraded) {
|
||||||
|
debug("transport had already been upgraded");
|
||||||
|
websocket.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("upgrading existing transport");
|
||||||
|
// transport error handling takes over
|
||||||
|
websocket.removeListener("error", onUpgradeError);
|
||||||
|
const transport = this.createTransport(req._query.transport, req);
|
||||||
|
// @ts-expect-error this option is only for WebSocket impl
|
||||||
|
transport.perMessageDeflate = this.opts.perMessageDeflate;
|
||||||
|
client._maybeUpgrade(transport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const closeConnection = (errorCode, errorContext) => abortUpgrade(socket, errorCode, errorContext);
|
||||||
|
this.handshake(req._query.transport, req, closeConnection);
|
||||||
|
}
|
||||||
|
function onUpgradeError() {
|
||||||
|
debug("websocket error before upgrade");
|
||||||
|
// websocket.close() not needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Captures upgrade requests for a http.Server.
|
||||||
|
*
|
||||||
|
* @param {http.Server} server
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
attach(server, options = {}) {
|
||||||
|
const path = this._computePath(options);
|
||||||
|
const destroyUpgradeTimeout = options.destroyUpgradeTimeout || 1000;
|
||||||
|
function check(req) {
|
||||||
|
// TODO use `path === new URL(...).pathname` in the next major release (ref: https://nodejs.org/api/url.html)
|
||||||
|
return path === req.url.slice(0, path.length);
|
||||||
|
}
|
||||||
|
// cache and clean up listeners
|
||||||
|
const listeners = server.listeners("request").slice(0);
|
||||||
|
server.removeAllListeners("request");
|
||||||
|
server.on("close", this.close.bind(this));
|
||||||
|
server.on("listening", this.init.bind(this));
|
||||||
|
// add request handler
|
||||||
|
server.on("request", (req, res) => {
|
||||||
|
if (check(req)) {
|
||||||
|
debug('intercepting request for path "%s"', path);
|
||||||
|
this.handleRequest(req, res);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let i = 0;
|
||||||
|
const l = listeners.length;
|
||||||
|
for (; i < l; i++) {
|
||||||
|
listeners[i].call(server, req, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (~this.opts.transports.indexOf("websocket")) {
|
||||||
|
server.on("upgrade", (req, socket, head) => {
|
||||||
|
if (check(req)) {
|
||||||
|
this.handleUpgrade(req, socket, head);
|
||||||
|
}
|
||||||
|
else if (false !== options.destroyUpgrade) {
|
||||||
|
// default node behavior is to disconnect when no handlers
|
||||||
|
// but by adding a handler, we prevent that
|
||||||
|
// and if no eio thing handles the upgrade
|
||||||
|
// then the socket needs to die!
|
||||||
|
setTimeout(function () {
|
||||||
|
// @ts-ignore
|
||||||
|
if (socket.writable && socket.bytesWritten <= 0) {
|
||||||
|
socket.on("error", (e) => {
|
||||||
|
debug("error while destroying upgrade: %s", e.message);
|
||||||
|
});
|
||||||
|
return socket.end();
|
||||||
|
}
|
||||||
|
}, destroyUpgradeTimeout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Server = Server;
|
||||||
|
/**
|
||||||
|
* Close the HTTP long-polling request
|
||||||
|
*
|
||||||
|
* @param res - the response object
|
||||||
|
* @param errorCode - the error code
|
||||||
|
* @param errorContext - additional error context
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function abortRequest(res, errorCode, errorContext) {
|
||||||
|
const statusCode = errorCode === Server.errors.FORBIDDEN ? 403 : 400;
|
||||||
|
const message = errorContext && errorContext.message
|
||||||
|
? errorContext.message
|
||||||
|
: Server.errorMessages[errorCode];
|
||||||
|
res.writeHead(statusCode, { "Content-Type": "application/json" });
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
code: errorCode,
|
||||||
|
message,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Close the WebSocket connection
|
||||||
|
*
|
||||||
|
* @param {net.Socket} socket
|
||||||
|
* @param {string} errorCode - the error code
|
||||||
|
* @param {object} errorContext - additional error context
|
||||||
|
*/
|
||||||
|
function abortUpgrade(socket, errorCode, errorContext = {}) {
|
||||||
|
socket.on("error", () => {
|
||||||
|
debug("ignoring error from closed connection");
|
||||||
|
});
|
||||||
|
if (socket.writable) {
|
||||||
|
const message = errorContext.message || Server.errorMessages[errorCode];
|
||||||
|
const length = Buffer.byteLength(message);
|
||||||
|
socket.write("HTTP/1.1 400 Bad Request\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"Content-type: text/html\r\n" +
|
||||||
|
"Content-Length: " +
|
||||||
|
length +
|
||||||
|
"\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
message);
|
||||||
|
}
|
||||||
|
socket.destroy();
|
||||||
|
}
|
||||||
|
/* eslint-disable */
|
||||||
|
/**
|
||||||
|
* From https://github.com/nodejs/node/blob/v8.4.0/lib/_http_common.js#L303-L354
|
||||||
|
*
|
||||||
|
* True if val contains an invalid field-vchar
|
||||||
|
* field-value = *( field-content / obs-fold )
|
||||||
|
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||||
|
* field-vchar = VCHAR / obs-text
|
||||||
|
*
|
||||||
|
* checkInvalidHeaderChar() is currently designed to be inlinable by v8,
|
||||||
|
* so take care when making changes to the implementation so that the source
|
||||||
|
* code size does not exceed v8's default max_inlined_source_size setting.
|
||||||
|
**/
|
||||||
|
// prettier-ignore
|
||||||
|
const validHdrChars = [
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0 - 15
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32 - 47
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48 - 63
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 95
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112 - 127
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128 ...
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // ... 255
|
||||||
|
];
|
||||||
|
function checkInvalidHeaderChar(val) {
|
||||||
|
val += "";
|
||||||
|
if (val.length < 1)
|
||||||
|
return false;
|
||||||
|
if (!validHdrChars[val.charCodeAt(0)]) {
|
||||||
|
debug('invalid header, index 0, char "%s"', val.charCodeAt(0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (val.length < 2)
|
||||||
|
return false;
|
||||||
|
if (!validHdrChars[val.charCodeAt(1)]) {
|
||||||
|
debug('invalid header, index 1, char "%s"', val.charCodeAt(1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (val.length < 3)
|
||||||
|
return false;
|
||||||
|
if (!validHdrChars[val.charCodeAt(2)]) {
|
||||||
|
debug('invalid header, index 2, char "%s"', val.charCodeAt(2));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (val.length < 4)
|
||||||
|
return false;
|
||||||
|
if (!validHdrChars[val.charCodeAt(3)]) {
|
||||||
|
debug('invalid header, index 3, char "%s"', val.charCodeAt(3));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (let i = 4; i < val.length; ++i) {
|
||||||
|
if (!validHdrChars[val.charCodeAt(i)]) {
|
||||||
|
debug('invalid header, index "%i", char "%s"', i, val.charCodeAt(i));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
180
node_modules/engine.io/build/socket.d.ts
generated
vendored
Normal file
180
node_modules/engine.io/build/socket.d.ts
generated
vendored
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
import { EventEmitter } from "events";
|
||||||
|
import type { IncomingMessage } from "http";
|
||||||
|
import type { EngineRequest, Transport } from "./transport";
|
||||||
|
import type { BaseServer } from "./server";
|
||||||
|
import type { RawData } from "engine.io-parser";
|
||||||
|
export interface SendOptions {
|
||||||
|
compress?: boolean;
|
||||||
|
}
|
||||||
|
type ReadyState = "opening" | "open" | "closing" | "closed";
|
||||||
|
type SendCallback = (transport: Transport) => void;
|
||||||
|
export declare class Socket extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* The revision of the protocol:
|
||||||
|
*
|
||||||
|
* - 3rd is used in Engine.IO v3 / Socket.IO v2
|
||||||
|
* - 4th is used in Engine.IO v4 and above / Socket.IO v3 and above
|
||||||
|
*
|
||||||
|
* It is found in the `EIO` query parameters of the HTTP requests.
|
||||||
|
*
|
||||||
|
* @see https://github.com/socketio/engine.io-protocol
|
||||||
|
*/
|
||||||
|
readonly protocol: number;
|
||||||
|
/**
|
||||||
|
* A reference to the first HTTP request of the session
|
||||||
|
*
|
||||||
|
* TODO for the next major release: remove it
|
||||||
|
*/
|
||||||
|
request: IncomingMessage;
|
||||||
|
/**
|
||||||
|
* The IP address of the client.
|
||||||
|
*/
|
||||||
|
readonly remoteAddress: string;
|
||||||
|
/**
|
||||||
|
* The current state of the socket.
|
||||||
|
*/
|
||||||
|
_readyState: ReadyState;
|
||||||
|
/**
|
||||||
|
* The current low-level transport.
|
||||||
|
*/
|
||||||
|
transport: Transport;
|
||||||
|
private server;
|
||||||
|
upgrading: boolean;
|
||||||
|
upgraded: boolean;
|
||||||
|
private writeBuffer;
|
||||||
|
private packetsFn;
|
||||||
|
private sentCallbackFn;
|
||||||
|
private cleanupFn;
|
||||||
|
private pingTimeoutTimer;
|
||||||
|
private pingIntervalTimer;
|
||||||
|
/**
|
||||||
|
* This is the session identifier that the client will use in the subsequent HTTP requests. It must not be shared with
|
||||||
|
* others parties, as it might lead to session hijacking.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private readonly id;
|
||||||
|
get readyState(): ReadyState;
|
||||||
|
set readyState(state: ReadyState);
|
||||||
|
constructor(id: string, server: BaseServer, transport: Transport, req: EngineRequest, protocol: number);
|
||||||
|
/**
|
||||||
|
* Called upon transport considered open.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private onOpen;
|
||||||
|
/**
|
||||||
|
* Called upon transport packet.
|
||||||
|
*
|
||||||
|
* @param {Object} packet
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private onPacket;
|
||||||
|
/**
|
||||||
|
* Called upon transport error.
|
||||||
|
*
|
||||||
|
* @param {Error} err - error object
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private onError;
|
||||||
|
/**
|
||||||
|
* Pings client every `this.pingInterval` and expects response
|
||||||
|
* within `this.pingTimeout` or closes connection.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private schedulePing;
|
||||||
|
/**
|
||||||
|
* Resets ping timeout.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private resetPingTimeout;
|
||||||
|
/**
|
||||||
|
* Attaches handlers for the given transport.
|
||||||
|
*
|
||||||
|
* @param {Transport} transport
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private setTransport;
|
||||||
|
/**
|
||||||
|
* Upon transport "drain" event
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private onDrain;
|
||||||
|
/**
|
||||||
|
* Upgrades socket to the given transport
|
||||||
|
*
|
||||||
|
* @param {Transport} transport
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_maybeUpgrade(transport: Transport): void;
|
||||||
|
/**
|
||||||
|
* Clears listeners and timers associated with current transport.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private clearTransport;
|
||||||
|
/**
|
||||||
|
* Called upon transport considered closed.
|
||||||
|
* Possible reasons: `ping timeout`, `client error`, `parse error`,
|
||||||
|
* `transport error`, `server close`, `transport close`
|
||||||
|
*/
|
||||||
|
private onClose;
|
||||||
|
/**
|
||||||
|
* Sends a message packet.
|
||||||
|
*
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Function} callback
|
||||||
|
* @return {Socket} for chaining
|
||||||
|
*/
|
||||||
|
send(data: RawData, options?: SendOptions, callback?: SendCallback): this;
|
||||||
|
/**
|
||||||
|
* Alias of {@link send}.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* @param options
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
write(data: RawData, options?: SendOptions, callback?: SendCallback): this;
|
||||||
|
/**
|
||||||
|
* Sends a packet.
|
||||||
|
*
|
||||||
|
* @param {String} type - packet type
|
||||||
|
* @param {String} data
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Function} callback
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private sendPacket;
|
||||||
|
/**
|
||||||
|
* Attempts to flush the packets buffer.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private flush;
|
||||||
|
/**
|
||||||
|
* Get available upgrades for this socket.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private getAvailableUpgrades;
|
||||||
|
/**
|
||||||
|
* Closes the socket and underlying transport.
|
||||||
|
*
|
||||||
|
* @param {Boolean} discard - optional, discard the transport
|
||||||
|
* @return {Socket} for chaining
|
||||||
|
*/
|
||||||
|
close(discard?: boolean): void;
|
||||||
|
/**
|
||||||
|
* Closes the underlying transport.
|
||||||
|
*
|
||||||
|
* @param {Boolean} discard
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private closeTransport;
|
||||||
|
}
|
||||||
|
export {};
|
||||||
460
node_modules/engine.io/build/socket.js
generated
vendored
Normal file
460
node_modules/engine.io/build/socket.js
generated
vendored
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Socket = void 0;
|
||||||
|
const events_1 = require("events");
|
||||||
|
const debug_1 = require("debug");
|
||||||
|
const timers_1 = require("timers");
|
||||||
|
const debug = (0, debug_1.default)("engine:socket");
|
||||||
|
class Socket extends events_1.EventEmitter {
|
||||||
|
get readyState() {
|
||||||
|
return this._readyState;
|
||||||
|
}
|
||||||
|
set readyState(state) {
|
||||||
|
debug("readyState updated from %s to %s", this._readyState, state);
|
||||||
|
this._readyState = state;
|
||||||
|
}
|
||||||
|
constructor(id, server, transport, req, protocol) {
|
||||||
|
super();
|
||||||
|
/**
|
||||||
|
* The current state of the socket.
|
||||||
|
*/
|
||||||
|
this._readyState = "opening";
|
||||||
|
/* private */ this.upgrading = false;
|
||||||
|
/* private */ this.upgraded = false;
|
||||||
|
this.writeBuffer = [];
|
||||||
|
this.packetsFn = [];
|
||||||
|
this.sentCallbackFn = [];
|
||||||
|
this.cleanupFn = [];
|
||||||
|
this.id = id;
|
||||||
|
this.server = server;
|
||||||
|
this.request = req;
|
||||||
|
this.protocol = protocol;
|
||||||
|
// Cache IP since it might not be in the req later
|
||||||
|
if (req) {
|
||||||
|
if (req.websocket && req.websocket._socket) {
|
||||||
|
this.remoteAddress = req.websocket._socket.remoteAddress;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.remoteAddress = req.connection.remoteAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO there is currently no way to get the IP address of the client when it connects with WebTransport
|
||||||
|
// see https://github.com/fails-components/webtransport/issues/114
|
||||||
|
}
|
||||||
|
this.pingTimeoutTimer = null;
|
||||||
|
this.pingIntervalTimer = null;
|
||||||
|
this.setTransport(transport);
|
||||||
|
this.onOpen();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called upon transport considered open.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onOpen() {
|
||||||
|
this.readyState = "open";
|
||||||
|
// sends an `open` packet
|
||||||
|
this.transport.sid = this.id;
|
||||||
|
this.sendPacket("open", JSON.stringify({
|
||||||
|
sid: this.id,
|
||||||
|
upgrades: this.getAvailableUpgrades(),
|
||||||
|
pingInterval: this.server.opts.pingInterval,
|
||||||
|
pingTimeout: this.server.opts.pingTimeout,
|
||||||
|
maxPayload: this.server.opts.maxHttpBufferSize,
|
||||||
|
}));
|
||||||
|
if (this.server.opts.initialPacket) {
|
||||||
|
this.sendPacket("message", this.server.opts.initialPacket);
|
||||||
|
}
|
||||||
|
this.emit("open");
|
||||||
|
if (this.protocol === 3) {
|
||||||
|
// in protocol v3, the client sends a ping, and the server answers with a pong
|
||||||
|
this.resetPingTimeout();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// in protocol v4, the server sends a ping, and the client answers with a pong
|
||||||
|
this.schedulePing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called upon transport packet.
|
||||||
|
*
|
||||||
|
* @param {Object} packet
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onPacket(packet) {
|
||||||
|
if ("open" !== this.readyState) {
|
||||||
|
return debug("packet received with closed socket");
|
||||||
|
}
|
||||||
|
// export packet event
|
||||||
|
debug(`received packet ${packet.type}`);
|
||||||
|
this.emit("packet", packet);
|
||||||
|
switch (packet.type) {
|
||||||
|
case "ping":
|
||||||
|
if (this.transport.protocol !== 3) {
|
||||||
|
this.onError(new Error("invalid heartbeat direction"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug("got ping");
|
||||||
|
this.pingTimeoutTimer.refresh();
|
||||||
|
this.sendPacket("pong");
|
||||||
|
this.emit("heartbeat");
|
||||||
|
break;
|
||||||
|
case "pong":
|
||||||
|
if (this.transport.protocol === 3) {
|
||||||
|
this.onError(new Error("invalid heartbeat direction"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug("got pong");
|
||||||
|
(0, timers_1.clearTimeout)(this.pingTimeoutTimer);
|
||||||
|
this.pingIntervalTimer.refresh();
|
||||||
|
this.emit("heartbeat");
|
||||||
|
break;
|
||||||
|
case "error":
|
||||||
|
this.onClose("parse error");
|
||||||
|
break;
|
||||||
|
case "message":
|
||||||
|
this.emit("data", packet.data);
|
||||||
|
this.emit("message", packet.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called upon transport error.
|
||||||
|
*
|
||||||
|
* @param {Error} err - error object
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onError(err) {
|
||||||
|
debug("transport error");
|
||||||
|
this.onClose("transport error", err);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Pings client every `this.pingInterval` and expects response
|
||||||
|
* within `this.pingTimeout` or closes connection.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
schedulePing() {
|
||||||
|
this.pingIntervalTimer = (0, timers_1.setTimeout)(() => {
|
||||||
|
debug("writing ping packet - expecting pong within %sms", this.server.opts.pingTimeout);
|
||||||
|
this.sendPacket("ping");
|
||||||
|
this.resetPingTimeout();
|
||||||
|
}, this.server.opts.pingInterval);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Resets ping timeout.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
resetPingTimeout() {
|
||||||
|
(0, timers_1.clearTimeout)(this.pingTimeoutTimer);
|
||||||
|
this.pingTimeoutTimer = (0, timers_1.setTimeout)(() => {
|
||||||
|
if (this.readyState === "closed")
|
||||||
|
return;
|
||||||
|
this.onClose("ping timeout");
|
||||||
|
}, this.protocol === 3
|
||||||
|
? this.server.opts.pingInterval + this.server.opts.pingTimeout
|
||||||
|
: this.server.opts.pingTimeout);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Attaches handlers for the given transport.
|
||||||
|
*
|
||||||
|
* @param {Transport} transport
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
setTransport(transport) {
|
||||||
|
const onError = this.onError.bind(this);
|
||||||
|
const onReady = () => this.flush();
|
||||||
|
const onPacket = this.onPacket.bind(this);
|
||||||
|
const onDrain = this.onDrain.bind(this);
|
||||||
|
const onClose = this.onClose.bind(this, "transport close");
|
||||||
|
this.transport = transport;
|
||||||
|
this.transport.once("error", onError);
|
||||||
|
this.transport.on("ready", onReady);
|
||||||
|
this.transport.on("packet", onPacket);
|
||||||
|
this.transport.on("drain", onDrain);
|
||||||
|
this.transport.once("close", onClose);
|
||||||
|
this.cleanupFn.push(function () {
|
||||||
|
transport.removeListener("error", onError);
|
||||||
|
transport.removeListener("ready", onReady);
|
||||||
|
transport.removeListener("packet", onPacket);
|
||||||
|
transport.removeListener("drain", onDrain);
|
||||||
|
transport.removeListener("close", onClose);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Upon transport "drain" event
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onDrain() {
|
||||||
|
if (this.sentCallbackFn.length > 0) {
|
||||||
|
debug("executing batch send callback");
|
||||||
|
const seqFn = this.sentCallbackFn.shift();
|
||||||
|
if (seqFn) {
|
||||||
|
for (let i = 0; i < seqFn.length; i++) {
|
||||||
|
seqFn[i](this.transport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Upgrades socket to the given transport
|
||||||
|
*
|
||||||
|
* @param {Transport} transport
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
/* private */ _maybeUpgrade(transport) {
|
||||||
|
debug('might upgrade socket transport from "%s" to "%s"', this.transport.name, transport.name);
|
||||||
|
this.upgrading = true;
|
||||||
|
// set transport upgrade timer
|
||||||
|
const upgradeTimeoutTimer = (0, timers_1.setTimeout)(() => {
|
||||||
|
debug("client did not complete upgrade - closing transport");
|
||||||
|
cleanup();
|
||||||
|
if ("open" === transport.readyState) {
|
||||||
|
transport.close();
|
||||||
|
}
|
||||||
|
}, this.server.opts.upgradeTimeout);
|
||||||
|
let checkIntervalTimer;
|
||||||
|
const onPacket = (packet) => {
|
||||||
|
if ("ping" === packet.type && "probe" === packet.data) {
|
||||||
|
debug("got probe ping packet, sending pong");
|
||||||
|
transport.send([{ type: "pong", data: "probe" }]);
|
||||||
|
this.emit("upgrading", transport);
|
||||||
|
clearInterval(checkIntervalTimer);
|
||||||
|
checkIntervalTimer = setInterval(check, 100);
|
||||||
|
}
|
||||||
|
else if ("upgrade" === packet.type && this.readyState !== "closed") {
|
||||||
|
debug("got upgrade packet - upgrading");
|
||||||
|
cleanup();
|
||||||
|
this.transport.discard();
|
||||||
|
this.upgraded = true;
|
||||||
|
this.clearTransport();
|
||||||
|
this.setTransport(transport);
|
||||||
|
this.emit("upgrade", transport);
|
||||||
|
this.flush();
|
||||||
|
if (this.readyState === "closing") {
|
||||||
|
transport.close(() => {
|
||||||
|
this.onClose("forced close");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cleanup();
|
||||||
|
transport.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// we force a polling cycle to ensure a fast upgrade
|
||||||
|
const check = () => {
|
||||||
|
if ("polling" === this.transport.name && this.transport.writable) {
|
||||||
|
debug("writing a noop packet to polling for fast upgrade");
|
||||||
|
this.transport.send([{ type: "noop" }]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const cleanup = () => {
|
||||||
|
this.upgrading = false;
|
||||||
|
clearInterval(checkIntervalTimer);
|
||||||
|
(0, timers_1.clearTimeout)(upgradeTimeoutTimer);
|
||||||
|
transport.removeListener("packet", onPacket);
|
||||||
|
transport.removeListener("close", onTransportClose);
|
||||||
|
transport.removeListener("error", onError);
|
||||||
|
this.removeListener("close", onClose);
|
||||||
|
};
|
||||||
|
const onError = (err) => {
|
||||||
|
debug("client did not complete upgrade - %s", err);
|
||||||
|
cleanup();
|
||||||
|
transport.close();
|
||||||
|
transport = null;
|
||||||
|
};
|
||||||
|
const onTransportClose = () => {
|
||||||
|
onError("transport closed");
|
||||||
|
};
|
||||||
|
const onClose = () => {
|
||||||
|
onError("socket closed");
|
||||||
|
};
|
||||||
|
transport.on("packet", onPacket);
|
||||||
|
transport.once("close", onTransportClose);
|
||||||
|
transport.once("error", onError);
|
||||||
|
this.once("close", onClose);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Clears listeners and timers associated with current transport.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
clearTransport() {
|
||||||
|
let cleanup;
|
||||||
|
const toCleanUp = this.cleanupFn.length;
|
||||||
|
for (let i = 0; i < toCleanUp; i++) {
|
||||||
|
cleanup = this.cleanupFn.shift();
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
// silence further transport errors and prevent uncaught exceptions
|
||||||
|
this.transport.on("error", function () {
|
||||||
|
debug("error triggered by discarded transport");
|
||||||
|
});
|
||||||
|
// ensure transport won't stay open
|
||||||
|
this.transport.close();
|
||||||
|
(0, timers_1.clearTimeout)(this.pingTimeoutTimer);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called upon transport considered closed.
|
||||||
|
* Possible reasons: `ping timeout`, `client error`, `parse error`,
|
||||||
|
* `transport error`, `server close`, `transport close`
|
||||||
|
*/
|
||||||
|
onClose(reason, description) {
|
||||||
|
if ("closed" !== this.readyState) {
|
||||||
|
this.readyState = "closed";
|
||||||
|
// clear timers
|
||||||
|
(0, timers_1.clearTimeout)(this.pingIntervalTimer);
|
||||||
|
(0, timers_1.clearTimeout)(this.pingTimeoutTimer);
|
||||||
|
// clean writeBuffer in next tick, so developers can still
|
||||||
|
// grab the writeBuffer on 'close' event
|
||||||
|
process.nextTick(() => {
|
||||||
|
this.writeBuffer = [];
|
||||||
|
});
|
||||||
|
this.packetsFn = [];
|
||||||
|
this.sentCallbackFn = [];
|
||||||
|
this.clearTransport();
|
||||||
|
this.emit("close", reason, description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sends a message packet.
|
||||||
|
*
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Function} callback
|
||||||
|
* @return {Socket} for chaining
|
||||||
|
*/
|
||||||
|
send(data, options, callback) {
|
||||||
|
this.sendPacket("message", data, options, callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Alias of {@link send}.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* @param options
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
write(data, options, callback) {
|
||||||
|
this.sendPacket("message", data, options, callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sends a packet.
|
||||||
|
*
|
||||||
|
* @param {String} type - packet type
|
||||||
|
* @param {String} data
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Function} callback
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
sendPacket(type, data, options = {}, callback) {
|
||||||
|
if ("function" === typeof options) {
|
||||||
|
callback = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
if ("closing" !== this.readyState && "closed" !== this.readyState) {
|
||||||
|
debug('sending packet "%s" (%s)', type, data);
|
||||||
|
// compression is enabled by default
|
||||||
|
options.compress = options.compress !== false;
|
||||||
|
const packet = {
|
||||||
|
type,
|
||||||
|
options: options,
|
||||||
|
};
|
||||||
|
if (data)
|
||||||
|
packet.data = data;
|
||||||
|
// exports packetCreate event
|
||||||
|
this.emit("packetCreate", packet);
|
||||||
|
this.writeBuffer.push(packet);
|
||||||
|
// add send callback to object, if defined
|
||||||
|
if ("function" === typeof callback)
|
||||||
|
this.packetsFn.push(callback);
|
||||||
|
this.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Attempts to flush the packets buffer.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
flush() {
|
||||||
|
if ("closed" !== this.readyState &&
|
||||||
|
this.transport.writable &&
|
||||||
|
this.writeBuffer.length) {
|
||||||
|
debug("flushing buffer to transport");
|
||||||
|
this.emit("flush", this.writeBuffer);
|
||||||
|
this.server.emit("flush", this, this.writeBuffer);
|
||||||
|
const wbuf = this.writeBuffer;
|
||||||
|
this.writeBuffer = [];
|
||||||
|
if (this.packetsFn.length) {
|
||||||
|
this.sentCallbackFn.push(this.packetsFn);
|
||||||
|
this.packetsFn = [];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.sentCallbackFn.push(null);
|
||||||
|
}
|
||||||
|
this.transport.send(wbuf);
|
||||||
|
this.emit("drain");
|
||||||
|
this.server.emit("drain", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get available upgrades for this socket.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getAvailableUpgrades() {
|
||||||
|
const availableUpgrades = [];
|
||||||
|
const allUpgrades = this.server.upgrades(this.transport.name);
|
||||||
|
for (let i = 0; i < allUpgrades.length; ++i) {
|
||||||
|
const upg = allUpgrades[i];
|
||||||
|
if (this.server.opts.transports.indexOf(upg) !== -1) {
|
||||||
|
availableUpgrades.push(upg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return availableUpgrades;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Closes the socket and underlying transport.
|
||||||
|
*
|
||||||
|
* @param {Boolean} discard - optional, discard the transport
|
||||||
|
* @return {Socket} for chaining
|
||||||
|
*/
|
||||||
|
close(discard) {
|
||||||
|
if (discard &&
|
||||||
|
(this.readyState === "open" || this.readyState === "closing")) {
|
||||||
|
return this.closeTransport(discard);
|
||||||
|
}
|
||||||
|
if ("open" !== this.readyState)
|
||||||
|
return;
|
||||||
|
this.readyState = "closing";
|
||||||
|
if (this.writeBuffer.length) {
|
||||||
|
debug("there are %d remaining packets in the buffer, waiting for the 'drain' event", this.writeBuffer.length);
|
||||||
|
this.once("drain", () => {
|
||||||
|
debug("all packets have been sent, closing the transport");
|
||||||
|
this.closeTransport(discard);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug("the buffer is empty, closing the transport right away");
|
||||||
|
this.closeTransport(discard);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Closes the underlying transport.
|
||||||
|
*
|
||||||
|
* @param {Boolean} discard
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
closeTransport(discard) {
|
||||||
|
debug("closing the transport (discard? %s)", !!discard);
|
||||||
|
if (discard)
|
||||||
|
this.transport.discard();
|
||||||
|
this.transport.close(this.onClose.bind(this, "forced close"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Socket = Socket;
|
||||||
135
node_modules/engine.io/build/transport.d.ts
generated
vendored
Normal file
135
node_modules/engine.io/build/transport.d.ts
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
import { EventEmitter } from "events";
|
||||||
|
import * as parser_v4 from "engine.io-parser";
|
||||||
|
import * as parser_v3 from "./parser-v3/index";
|
||||||
|
import type { IncomingMessage, ServerResponse } from "http";
|
||||||
|
import { Packet, RawData } from "engine.io-parser";
|
||||||
|
import type { WebSocket } from "ws";
|
||||||
|
type ReadyState = "open" | "closing" | "closed";
|
||||||
|
export type EngineRequest = IncomingMessage & {
|
||||||
|
_query: Record<string, string>;
|
||||||
|
res?: ServerResponse;
|
||||||
|
cleanup?: Function;
|
||||||
|
websocket?: WebSocket & {
|
||||||
|
_socket?: {
|
||||||
|
remoteAddress: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export declare abstract class Transport extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* The session ID.
|
||||||
|
*/
|
||||||
|
sid: string;
|
||||||
|
/**
|
||||||
|
* Whether the transport is currently ready to send packets.
|
||||||
|
*/
|
||||||
|
writable: boolean;
|
||||||
|
/**
|
||||||
|
* The revision of the protocol:
|
||||||
|
*
|
||||||
|
* - 3 is used in Engine.IO v3 / Socket.IO v2
|
||||||
|
* - 4 is used in Engine.IO v4 and above / Socket.IO v3 and above
|
||||||
|
*
|
||||||
|
* It is found in the `EIO` query parameters of the HTTP requests.
|
||||||
|
*
|
||||||
|
* @see https://github.com/socketio/engine.io-protocol
|
||||||
|
*/
|
||||||
|
protocol: 3 | 4;
|
||||||
|
/**
|
||||||
|
* The current state of the transport.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected _readyState: ReadyState;
|
||||||
|
/**
|
||||||
|
* Whether the transport is discarded and can be safely closed (used during upgrade).
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected discarded: boolean;
|
||||||
|
/**
|
||||||
|
* The parser to use (depends on the revision of the {@link Transport#protocol}.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected parser: typeof parser_v4 | typeof parser_v3;
|
||||||
|
/**
|
||||||
|
* Whether the transport supports binary payloads (else it will be base64-encoded)
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected supportsBinary: boolean;
|
||||||
|
get readyState(): ReadyState;
|
||||||
|
set readyState(state: ReadyState);
|
||||||
|
/**
|
||||||
|
* The list of transports this transport can be upgraded to.
|
||||||
|
*/
|
||||||
|
static upgradesTo: string[];
|
||||||
|
/**
|
||||||
|
* Transport constructor.
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
*/
|
||||||
|
constructor(req: {
|
||||||
|
_query: Record<string, string>;
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
* Flags the transport as discarded.
|
||||||
|
*
|
||||||
|
* @package
|
||||||
|
*/
|
||||||
|
discard(): void;
|
||||||
|
/**
|
||||||
|
* Called with an incoming HTTP request.
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
* @package
|
||||||
|
*/
|
||||||
|
onRequest(req: any): void;
|
||||||
|
/**
|
||||||
|
* Closes the transport.
|
||||||
|
*
|
||||||
|
* @package
|
||||||
|
*/
|
||||||
|
close(fn?: () => void): void;
|
||||||
|
/**
|
||||||
|
* Called with a transport error.
|
||||||
|
*
|
||||||
|
* @param {String} msg - message error
|
||||||
|
* @param {Object} desc - error description
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected onError(msg: string, desc?: any): void;
|
||||||
|
/**
|
||||||
|
* Called with parsed out a packets from the data stream.
|
||||||
|
*
|
||||||
|
* @param {Object} packet
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected onPacket(packet: Packet): void;
|
||||||
|
/**
|
||||||
|
* Called with the encoded packet data.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected onData(data: RawData): void;
|
||||||
|
/**
|
||||||
|
* Called upon transport close.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected onClose(): void;
|
||||||
|
/**
|
||||||
|
* The name of the transport.
|
||||||
|
*/
|
||||||
|
abstract get name(): string;
|
||||||
|
/**
|
||||||
|
* Sends an array of packets.
|
||||||
|
*
|
||||||
|
* @param {Array} packets
|
||||||
|
* @package
|
||||||
|
*/
|
||||||
|
abstract send(packets: Packet[]): void;
|
||||||
|
/**
|
||||||
|
* Closes the transport.
|
||||||
|
*/
|
||||||
|
abstract doClose(fn?: () => void): void;
|
||||||
|
}
|
||||||
|
export {};
|
||||||
121
node_modules/engine.io/build/transport.js
generated
vendored
Normal file
121
node_modules/engine.io/build/transport.js
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Transport = void 0;
|
||||||
|
const events_1 = require("events");
|
||||||
|
const parser_v4 = require("engine.io-parser");
|
||||||
|
const parser_v3 = require("./parser-v3/index");
|
||||||
|
const debug_1 = require("debug");
|
||||||
|
const debug = (0, debug_1.default)("engine:transport");
|
||||||
|
function noop() { }
|
||||||
|
class Transport extends events_1.EventEmitter {
|
||||||
|
get readyState() {
|
||||||
|
return this._readyState;
|
||||||
|
}
|
||||||
|
set readyState(state) {
|
||||||
|
debug("readyState updated from %s to %s (%s)", this._readyState, state, this.name);
|
||||||
|
this._readyState = state;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Transport constructor.
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
*/
|
||||||
|
constructor(req) {
|
||||||
|
super();
|
||||||
|
/**
|
||||||
|
* Whether the transport is currently ready to send packets.
|
||||||
|
*/
|
||||||
|
this.writable = false;
|
||||||
|
/**
|
||||||
|
* The current state of the transport.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this._readyState = "open";
|
||||||
|
/**
|
||||||
|
* Whether the transport is discarded and can be safely closed (used during upgrade).
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
this.discarded = false;
|
||||||
|
this.protocol = req._query.EIO === "4" ? 4 : 3; // 3rd revision by default
|
||||||
|
this.parser = this.protocol === 4 ? parser_v4 : parser_v3;
|
||||||
|
this.supportsBinary = !(req._query && req._query.b64);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Flags the transport as discarded.
|
||||||
|
*
|
||||||
|
* @package
|
||||||
|
*/
|
||||||
|
discard() {
|
||||||
|
this.discarded = true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called with an incoming HTTP request.
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
* @package
|
||||||
|
*/
|
||||||
|
onRequest(req) { }
|
||||||
|
/**
|
||||||
|
* Closes the transport.
|
||||||
|
*
|
||||||
|
* @package
|
||||||
|
*/
|
||||||
|
close(fn) {
|
||||||
|
if ("closed" === this.readyState || "closing" === this.readyState)
|
||||||
|
return;
|
||||||
|
this.readyState = "closing";
|
||||||
|
this.doClose(fn || noop);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called with a transport error.
|
||||||
|
*
|
||||||
|
* @param {String} msg - message error
|
||||||
|
* @param {Object} desc - error description
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
onError(msg, desc) {
|
||||||
|
if (this.listeners("error").length) {
|
||||||
|
const err = new Error(msg);
|
||||||
|
// @ts-ignore
|
||||||
|
err.type = "TransportError";
|
||||||
|
// @ts-ignore
|
||||||
|
err.description = desc;
|
||||||
|
this.emit("error", err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("ignored transport error %s (%s)", msg, desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called with parsed out a packets from the data stream.
|
||||||
|
*
|
||||||
|
* @param {Object} packet
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
onPacket(packet) {
|
||||||
|
this.emit("packet", packet);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called with the encoded packet data.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
onData(data) {
|
||||||
|
this.onPacket(this.parser.decodePacket(data));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Called upon transport close.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
onClose() {
|
||||||
|
this.readyState = "closed";
|
||||||
|
this.emit("close");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Transport = Transport;
|
||||||
|
/**
|
||||||
|
* The list of transports this transport can be upgraded to.
|
||||||
|
*/
|
||||||
|
Transport.upgradesTo = [];
|
||||||
7
node_modules/engine.io/build/transports-uws/index.d.ts
generated
vendored
Normal file
7
node_modules/engine.io/build/transports-uws/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { Polling } from "./polling";
|
||||||
|
import { WebSocket } from "./websocket";
|
||||||
|
declare const _default: {
|
||||||
|
polling: typeof Polling;
|
||||||
|
websocket: typeof WebSocket;
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
8
node_modules/engine.io/build/transports-uws/index.js
generated
vendored
Normal file
8
node_modules/engine.io/build/transports-uws/index.js
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const polling_1 = require("./polling");
|
||||||
|
const websocket_1 = require("./websocket");
|
||||||
|
exports.default = {
|
||||||
|
polling: polling_1.Polling,
|
||||||
|
websocket: websocket_1.WebSocket,
|
||||||
|
};
|
||||||
99
node_modules/engine.io/build/transports-uws/polling.d.ts
generated
vendored
Normal file
99
node_modules/engine.io/build/transports-uws/polling.d.ts
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import { Transport } from "../transport";
|
||||||
|
export declare class Polling extends Transport {
|
||||||
|
maxHttpBufferSize: number;
|
||||||
|
httpCompression: any;
|
||||||
|
private req;
|
||||||
|
private res;
|
||||||
|
private dataReq;
|
||||||
|
private dataRes;
|
||||||
|
private shouldClose;
|
||||||
|
private readonly closeTimeout;
|
||||||
|
/**
|
||||||
|
* HTTP polling constructor.
|
||||||
|
*/
|
||||||
|
constructor(req: any);
|
||||||
|
/**
|
||||||
|
* Transport name
|
||||||
|
*/
|
||||||
|
get name(): string;
|
||||||
|
/**
|
||||||
|
* Overrides onRequest.
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onRequest(req: any): void;
|
||||||
|
/**
|
||||||
|
* The client sends a request awaiting for us to send data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onPollRequest(req: any, res: any): void;
|
||||||
|
/**
|
||||||
|
* The client sends a request with data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onDataRequest(req: any, res: any): void;
|
||||||
|
/**
|
||||||
|
* Cleanup request.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private onDataRequestCleanup;
|
||||||
|
/**
|
||||||
|
* Processes the incoming data payload.
|
||||||
|
*
|
||||||
|
* @param {String} encoded payload
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onData(data: any): void;
|
||||||
|
/**
|
||||||
|
* Overrides onClose.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onClose(): void;
|
||||||
|
/**
|
||||||
|
* Writes a packet payload.
|
||||||
|
*
|
||||||
|
* @param {Object} packet
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
send(packets: any): void;
|
||||||
|
/**
|
||||||
|
* Writes data as response to poll request.
|
||||||
|
*
|
||||||
|
* @param {String} data
|
||||||
|
* @param {Object} options
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
write(data: any, options: any): void;
|
||||||
|
/**
|
||||||
|
* Performs the write.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
doWrite(data: any, options: any, callback: any): void;
|
||||||
|
/**
|
||||||
|
* Compresses data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
compress(data: any, encoding: any, callback: any): void;
|
||||||
|
/**
|
||||||
|
* Closes the transport.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
doClose(fn: any): void;
|
||||||
|
/**
|
||||||
|
* Returns headers for a response.
|
||||||
|
*
|
||||||
|
* @param req - request
|
||||||
|
* @param {Object} extra headers
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
headers(req: any, headers: any): any;
|
||||||
|
}
|
||||||
364
node_modules/engine.io/build/transports-uws/polling.js
generated
vendored
Normal file
364
node_modules/engine.io/build/transports-uws/polling.js
generated
vendored
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Polling = void 0;
|
||||||
|
const transport_1 = require("../transport");
|
||||||
|
const zlib_1 = require("zlib");
|
||||||
|
const accepts = require("accepts");
|
||||||
|
const debug_1 = require("debug");
|
||||||
|
const debug = (0, debug_1.default)("engine:polling");
|
||||||
|
const compressionMethods = {
|
||||||
|
gzip: zlib_1.createGzip,
|
||||||
|
deflate: zlib_1.createDeflate,
|
||||||
|
};
|
||||||
|
class Polling extends transport_1.Transport {
|
||||||
|
/**
|
||||||
|
* HTTP polling constructor.
|
||||||
|
*/
|
||||||
|
constructor(req) {
|
||||||
|
super(req);
|
||||||
|
this.closeTimeout = 30 * 1000;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Transport name
|
||||||
|
*/
|
||||||
|
get name() {
|
||||||
|
return "polling";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Overrides onRequest.
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onRequest(req) {
|
||||||
|
const res = req.res;
|
||||||
|
// remove the reference to the ServerResponse object (as the first request of the session is kept in memory by default)
|
||||||
|
req.res = null;
|
||||||
|
if (req.getMethod() === "get") {
|
||||||
|
this.onPollRequest(req, res);
|
||||||
|
}
|
||||||
|
else if (req.getMethod() === "post") {
|
||||||
|
this.onDataRequest(req, res);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res.writeStatus("500 Internal Server Error");
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The client sends a request awaiting for us to send data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onPollRequest(req, res) {
|
||||||
|
if (this.req) {
|
||||||
|
debug("request overlap");
|
||||||
|
// assert: this.res, '.req and .res should be (un)set together'
|
||||||
|
this.onError("overlap from client");
|
||||||
|
res.writeStatus("500 Internal Server Error");
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug("setting request");
|
||||||
|
this.req = req;
|
||||||
|
this.res = res;
|
||||||
|
const onClose = () => {
|
||||||
|
this.writable = false;
|
||||||
|
this.onError("poll connection closed prematurely");
|
||||||
|
};
|
||||||
|
const cleanup = () => {
|
||||||
|
this.req = this.res = null;
|
||||||
|
};
|
||||||
|
req.cleanup = cleanup;
|
||||||
|
res.onAborted(onClose);
|
||||||
|
this.writable = true;
|
||||||
|
this.emit("ready");
|
||||||
|
// if we're still writable but had a pending close, trigger an empty send
|
||||||
|
if (this.writable && this.shouldClose) {
|
||||||
|
debug("triggering empty send to append close packet");
|
||||||
|
this.send([{ type: "noop" }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The client sends a request with data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onDataRequest(req, res) {
|
||||||
|
if (this.dataReq) {
|
||||||
|
// assert: this.dataRes, '.dataReq and .dataRes should be (un)set together'
|
||||||
|
this.onError("data request overlap from client");
|
||||||
|
res.writeStatus("500 Internal Server Error");
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const expectedContentLength = Number(req.headers["content-length"]);
|
||||||
|
if (!expectedContentLength) {
|
||||||
|
this.onError("content-length header required");
|
||||||
|
res.writeStatus("411 Length Required").end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (expectedContentLength > this.maxHttpBufferSize) {
|
||||||
|
this.onError("payload too large");
|
||||||
|
res.writeStatus("413 Payload Too Large").end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const isBinary = "application/octet-stream" === req.headers["content-type"];
|
||||||
|
if (isBinary && this.protocol === 4) {
|
||||||
|
return this.onError("invalid content");
|
||||||
|
}
|
||||||
|
this.dataReq = req;
|
||||||
|
this.dataRes = res;
|
||||||
|
let buffer;
|
||||||
|
let offset = 0;
|
||||||
|
const headers = {
|
||||||
|
// text/html is required instead of text/plain to avoid an
|
||||||
|
// unwanted download dialog on certain user-agents (GH-43)
|
||||||
|
"Content-Type": "text/html",
|
||||||
|
};
|
||||||
|
this.headers(req, headers);
|
||||||
|
for (let key in headers) {
|
||||||
|
res.writeHeader(key, String(headers[key]));
|
||||||
|
}
|
||||||
|
const onEnd = (buffer) => {
|
||||||
|
this.onData(buffer.toString());
|
||||||
|
this.onDataRequestCleanup();
|
||||||
|
res.cork(() => {
|
||||||
|
res.end("ok");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
res.onAborted(() => {
|
||||||
|
this.onDataRequestCleanup();
|
||||||
|
this.onError("data request connection closed prematurely");
|
||||||
|
});
|
||||||
|
res.onData((arrayBuffer, isLast) => {
|
||||||
|
const totalLength = offset + arrayBuffer.byteLength;
|
||||||
|
if (totalLength > expectedContentLength) {
|
||||||
|
this.onError("content-length mismatch");
|
||||||
|
res.close(); // calls onAborted
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!buffer) {
|
||||||
|
if (isLast) {
|
||||||
|
onEnd(Buffer.from(arrayBuffer));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer = Buffer.allocUnsafe(expectedContentLength);
|
||||||
|
}
|
||||||
|
Buffer.from(arrayBuffer).copy(buffer, offset);
|
||||||
|
if (isLast) {
|
||||||
|
if (totalLength != expectedContentLength) {
|
||||||
|
this.onError("content-length mismatch");
|
||||||
|
res.writeStatus("400 Content-Length Mismatch").end();
|
||||||
|
this.onDataRequestCleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onEnd(buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
offset = totalLength;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Cleanup request.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onDataRequestCleanup() {
|
||||||
|
this.dataReq = this.dataRes = null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Processes the incoming data payload.
|
||||||
|
*
|
||||||
|
* @param {String} encoded payload
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onData(data) {
|
||||||
|
debug('received "%s"', data);
|
||||||
|
const callback = (packet) => {
|
||||||
|
if ("close" === packet.type) {
|
||||||
|
debug("got xhr close packet");
|
||||||
|
this.onClose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.onPacket(packet);
|
||||||
|
};
|
||||||
|
if (this.protocol === 3) {
|
||||||
|
this.parser.decodePayload(data, callback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.parser.decodePayload(data).forEach(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Overrides onClose.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onClose() {
|
||||||
|
if (this.writable) {
|
||||||
|
// close pending poll request
|
||||||
|
this.send([{ type: "noop" }]);
|
||||||
|
}
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes a packet payload.
|
||||||
|
*
|
||||||
|
* @param {Object} packet
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
send(packets) {
|
||||||
|
this.writable = false;
|
||||||
|
if (this.shouldClose) {
|
||||||
|
debug("appending close packet to payload");
|
||||||
|
packets.push({ type: "close" });
|
||||||
|
this.shouldClose();
|
||||||
|
this.shouldClose = null;
|
||||||
|
}
|
||||||
|
const doWrite = (data) => {
|
||||||
|
const compress = packets.some((packet) => {
|
||||||
|
return packet.options && packet.options.compress;
|
||||||
|
});
|
||||||
|
this.write(data, { compress });
|
||||||
|
};
|
||||||
|
if (this.protocol === 3) {
|
||||||
|
this.parser.encodePayload(packets, this.supportsBinary, doWrite);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.parser.encodePayload(packets, doWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes data as response to poll request.
|
||||||
|
*
|
||||||
|
* @param {String} data
|
||||||
|
* @param {Object} options
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
write(data, options) {
|
||||||
|
debug('writing "%s"', data);
|
||||||
|
this.doWrite(data, options, () => {
|
||||||
|
this.req.cleanup();
|
||||||
|
this.emit("drain");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Performs the write.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
doWrite(data, options, callback) {
|
||||||
|
// explicit UTF-8 is required for pages not served under utf
|
||||||
|
const isString = typeof data === "string";
|
||||||
|
const contentType = isString
|
||||||
|
? "text/plain; charset=UTF-8"
|
||||||
|
: "application/octet-stream";
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": contentType,
|
||||||
|
};
|
||||||
|
const respond = (data) => {
|
||||||
|
this.headers(this.req, headers);
|
||||||
|
this.res.cork(() => {
|
||||||
|
Object.keys(headers).forEach((key) => {
|
||||||
|
this.res.writeHeader(key, String(headers[key]));
|
||||||
|
});
|
||||||
|
this.res.end(data);
|
||||||
|
});
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
if (!this.httpCompression || !options.compress) {
|
||||||
|
respond(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const len = isString ? Buffer.byteLength(data) : data.length;
|
||||||
|
if (len < this.httpCompression.threshold) {
|
||||||
|
respond(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const encoding = accepts(this.req).encodings(["gzip", "deflate"]);
|
||||||
|
if (!encoding) {
|
||||||
|
respond(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.compress(data, encoding, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
this.res.writeStatus("500 Internal Server Error");
|
||||||
|
this.res.end();
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
headers["Content-Encoding"] = encoding;
|
||||||
|
respond(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Compresses data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
compress(data, encoding, callback) {
|
||||||
|
debug("compressing");
|
||||||
|
const buffers = [];
|
||||||
|
let nread = 0;
|
||||||
|
compressionMethods[encoding](this.httpCompression)
|
||||||
|
.on("error", callback)
|
||||||
|
.on("data", function (chunk) {
|
||||||
|
buffers.push(chunk);
|
||||||
|
nread += chunk.length;
|
||||||
|
})
|
||||||
|
.on("end", function () {
|
||||||
|
callback(null, Buffer.concat(buffers, nread));
|
||||||
|
})
|
||||||
|
.end(data);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Closes the transport.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
doClose(fn) {
|
||||||
|
debug("closing");
|
||||||
|
let closeTimeoutTimer;
|
||||||
|
const onClose = () => {
|
||||||
|
clearTimeout(closeTimeoutTimer);
|
||||||
|
fn();
|
||||||
|
this.onClose();
|
||||||
|
};
|
||||||
|
if (this.writable) {
|
||||||
|
debug("transport writable - closing right away");
|
||||||
|
this.send([{ type: "close" }]);
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
else if (this.discarded) {
|
||||||
|
debug("transport discarded - closing right away");
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("transport not writable - buffering orderly close");
|
||||||
|
this.shouldClose = onClose;
|
||||||
|
closeTimeoutTimer = setTimeout(onClose, this.closeTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns headers for a response.
|
||||||
|
*
|
||||||
|
* @param req - request
|
||||||
|
* @param {Object} extra headers
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
headers(req, headers) {
|
||||||
|
headers = headers || {};
|
||||||
|
// prevent XSS warnings on IE
|
||||||
|
// https://github.com/LearnBoost/socket.io/pull/1333
|
||||||
|
const ua = req.headers["user-agent"];
|
||||||
|
if (ua && (~ua.indexOf(";MSIE") || ~ua.indexOf("Trident/"))) {
|
||||||
|
headers["X-XSS-Protection"] = "0";
|
||||||
|
}
|
||||||
|
headers["cache-control"] = "no-store";
|
||||||
|
this.emit("headers", headers, req);
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Polling = Polling;
|
||||||
32
node_modules/engine.io/build/transports-uws/websocket.d.ts
generated
vendored
Normal file
32
node_modules/engine.io/build/transports-uws/websocket.d.ts
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { Transport } from "../transport";
|
||||||
|
export declare class WebSocket extends Transport {
|
||||||
|
protected perMessageDeflate: any;
|
||||||
|
private socket;
|
||||||
|
/**
|
||||||
|
* WebSocket transport
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
*/
|
||||||
|
constructor(req: any);
|
||||||
|
/**
|
||||||
|
* Transport name
|
||||||
|
*/
|
||||||
|
get name(): string;
|
||||||
|
/**
|
||||||
|
* Advertise upgrade support.
|
||||||
|
*/
|
||||||
|
get handlesUpgrades(): boolean;
|
||||||
|
/**
|
||||||
|
* Writes a packet payload.
|
||||||
|
*
|
||||||
|
* @param {Array} packets
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
send(packets: any): void;
|
||||||
|
/**
|
||||||
|
* Closes the transport.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
doClose(fn: any): void;
|
||||||
|
}
|
||||||
73
node_modules/engine.io/build/transports-uws/websocket.js
generated
vendored
Normal file
73
node_modules/engine.io/build/transports-uws/websocket.js
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.WebSocket = void 0;
|
||||||
|
const transport_1 = require("../transport");
|
||||||
|
const debug_1 = require("debug");
|
||||||
|
const debug = (0, debug_1.default)("engine:ws");
|
||||||
|
class WebSocket extends transport_1.Transport {
|
||||||
|
/**
|
||||||
|
* WebSocket transport
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
*/
|
||||||
|
constructor(req) {
|
||||||
|
super(req);
|
||||||
|
this.writable = false;
|
||||||
|
this.perMessageDeflate = null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Transport name
|
||||||
|
*/
|
||||||
|
get name() {
|
||||||
|
return "websocket";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Advertise upgrade support.
|
||||||
|
*/
|
||||||
|
get handlesUpgrades() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes a packet payload.
|
||||||
|
*
|
||||||
|
* @param {Array} packets
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
send(packets) {
|
||||||
|
this.writable = false;
|
||||||
|
for (let i = 0; i < packets.length; i++) {
|
||||||
|
const packet = packets[i];
|
||||||
|
const isLast = i + 1 === packets.length;
|
||||||
|
const send = (data) => {
|
||||||
|
const isBinary = typeof data !== "string";
|
||||||
|
const compress = this.perMessageDeflate &&
|
||||||
|
Buffer.byteLength(data) > this.perMessageDeflate.threshold;
|
||||||
|
debug('writing "%s"', data);
|
||||||
|
this.socket.send(data, isBinary, compress);
|
||||||
|
if (isLast) {
|
||||||
|
this.emit("drain");
|
||||||
|
this.writable = true;
|
||||||
|
this.emit("ready");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (packet.options && typeof packet.options.wsPreEncoded === "string") {
|
||||||
|
send(packet.options.wsPreEncoded);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.parser.encodePacket(packet, this.supportsBinary, send);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Closes the transport.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
doClose(fn) {
|
||||||
|
debug("closing");
|
||||||
|
fn && fn();
|
||||||
|
// call fn first since socket.end() immediately emits a "close" event
|
||||||
|
this.socket.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.WebSocket = WebSocket;
|
||||||
17
node_modules/engine.io/build/transports/index.d.ts
generated
vendored
Normal file
17
node_modules/engine.io/build/transports/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Polling as XHR } from "./polling";
|
||||||
|
import { WebSocket } from "./websocket";
|
||||||
|
import { WebTransport } from "./webtransport";
|
||||||
|
import type { EngineRequest } from "../transport";
|
||||||
|
declare const _default: {
|
||||||
|
polling: typeof polling;
|
||||||
|
websocket: typeof WebSocket;
|
||||||
|
webtransport: typeof WebTransport;
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
|
/**
|
||||||
|
* Polling polymorphic constructor.
|
||||||
|
*/
|
||||||
|
declare function polling(req: EngineRequest): XHR;
|
||||||
|
declare namespace polling {
|
||||||
|
var upgradesTo: string[];
|
||||||
|
}
|
||||||
23
node_modules/engine.io/build/transports/index.js
generated
vendored
Normal file
23
node_modules/engine.io/build/transports/index.js
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const polling_1 = require("./polling");
|
||||||
|
const polling_jsonp_1 = require("./polling-jsonp");
|
||||||
|
const websocket_1 = require("./websocket");
|
||||||
|
const webtransport_1 = require("./webtransport");
|
||||||
|
exports.default = {
|
||||||
|
polling,
|
||||||
|
websocket: websocket_1.WebSocket,
|
||||||
|
webtransport: webtransport_1.WebTransport,
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Polling polymorphic constructor.
|
||||||
|
*/
|
||||||
|
function polling(req) {
|
||||||
|
if ("string" === typeof req._query.j) {
|
||||||
|
return new polling_jsonp_1.JSONP(req);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new polling_1.Polling(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
polling.upgradesTo = ["websocket", "webtransport"];
|
||||||
12
node_modules/engine.io/build/transports/polling-jsonp.d.ts
generated
vendored
Normal file
12
node_modules/engine.io/build/transports/polling-jsonp.d.ts
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Polling } from "./polling";
|
||||||
|
import type { RawData } from "engine.io-parser";
|
||||||
|
export declare class JSONP extends Polling {
|
||||||
|
private readonly head;
|
||||||
|
private readonly foot;
|
||||||
|
/**
|
||||||
|
* JSON-P polling transport.
|
||||||
|
*/
|
||||||
|
constructor(req: any);
|
||||||
|
onData(data: RawData): void;
|
||||||
|
doWrite(data: any, options: any, callback: any): void;
|
||||||
|
}
|
||||||
41
node_modules/engine.io/build/transports/polling-jsonp.js
generated
vendored
Normal file
41
node_modules/engine.io/build/transports/polling-jsonp.js
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.JSONP = void 0;
|
||||||
|
const polling_1 = require("./polling");
|
||||||
|
const qs = require("querystring");
|
||||||
|
const rDoubleSlashes = /\\\\n/g;
|
||||||
|
const rSlashes = /(\\)?\\n/g;
|
||||||
|
class JSONP extends polling_1.Polling {
|
||||||
|
/**
|
||||||
|
* JSON-P polling transport.
|
||||||
|
*/
|
||||||
|
constructor(req) {
|
||||||
|
super(req);
|
||||||
|
this.head = "___eio[" + (req._query.j || "").replace(/[^0-9]/g, "") + "](";
|
||||||
|
this.foot = ");";
|
||||||
|
}
|
||||||
|
onData(data) {
|
||||||
|
// we leverage the qs module so that we get built-in DoS protection
|
||||||
|
// and the fast alternative to decodeURIComponent
|
||||||
|
data = qs.parse(data).d;
|
||||||
|
if ("string" === typeof data) {
|
||||||
|
// client will send already escaped newlines as \\\\n and newlines as \\n
|
||||||
|
// \\n must be replaced with \n and \\\\n with \\n
|
||||||
|
data = data.replace(rSlashes, function (match, slashes) {
|
||||||
|
return slashes ? match : "\n";
|
||||||
|
});
|
||||||
|
super.onData(data.replace(rDoubleSlashes, "\\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doWrite(data, options, callback) {
|
||||||
|
// we must output valid javascript, not valid json
|
||||||
|
// see: http://timelessrepo.com/json-isnt-a-javascript-subset
|
||||||
|
const js = JSON.stringify(data)
|
||||||
|
.replace(/\u2028/g, "\\u2028")
|
||||||
|
.replace(/\u2029/g, "\\u2029");
|
||||||
|
// prepare response
|
||||||
|
data = this.head + js + this.foot;
|
||||||
|
super.doWrite(data, options, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.JSONP = JSONP;
|
||||||
87
node_modules/engine.io/build/transports/polling.d.ts
generated
vendored
Normal file
87
node_modules/engine.io/build/transports/polling.d.ts
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { EngineRequest, Transport } from "../transport";
|
||||||
|
import type { Packet, RawData } from "engine.io-parser";
|
||||||
|
export declare class Polling extends Transport {
|
||||||
|
maxHttpBufferSize: number;
|
||||||
|
httpCompression: any;
|
||||||
|
private req;
|
||||||
|
private res;
|
||||||
|
private dataReq;
|
||||||
|
private dataRes;
|
||||||
|
private shouldClose;
|
||||||
|
private readonly closeTimeout;
|
||||||
|
/**
|
||||||
|
* HTTP polling constructor.
|
||||||
|
*/
|
||||||
|
constructor(req: any);
|
||||||
|
/**
|
||||||
|
* Transport name
|
||||||
|
*/
|
||||||
|
get name(): string;
|
||||||
|
/**
|
||||||
|
* Overrides onRequest.
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
* @package
|
||||||
|
*/
|
||||||
|
onRequest(req: EngineRequest): void;
|
||||||
|
/**
|
||||||
|
* The client sends a request awaiting for us to send data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private onPollRequest;
|
||||||
|
/**
|
||||||
|
* The client sends a request with data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private onDataRequest;
|
||||||
|
/**
|
||||||
|
* Processes the incoming data payload.
|
||||||
|
*
|
||||||
|
* @param data - encoded payload
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
onData(data: RawData): void;
|
||||||
|
/**
|
||||||
|
* Overrides onClose.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onClose(): void;
|
||||||
|
send(packets: Packet[]): void;
|
||||||
|
/**
|
||||||
|
* Writes data as response to poll request.
|
||||||
|
*
|
||||||
|
* @param {String} data
|
||||||
|
* @param {Object} options
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private write;
|
||||||
|
/**
|
||||||
|
* Performs the write.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected doWrite(data: any, options: any, callback: any): void;
|
||||||
|
/**
|
||||||
|
* Compresses data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private compress;
|
||||||
|
/**
|
||||||
|
* Closes the transport.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
doClose(fn: () => void): void;
|
||||||
|
/**
|
||||||
|
* Returns headers for a response.
|
||||||
|
*
|
||||||
|
* @param {http.IncomingMessage} req
|
||||||
|
* @param {Object} headers - extra headers
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private headers;
|
||||||
|
}
|
||||||
332
node_modules/engine.io/build/transports/polling.js
generated
vendored
Normal file
332
node_modules/engine.io/build/transports/polling.js
generated
vendored
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Polling = void 0;
|
||||||
|
const transport_1 = require("../transport");
|
||||||
|
const zlib_1 = require("zlib");
|
||||||
|
const accepts = require("accepts");
|
||||||
|
const debug_1 = require("debug");
|
||||||
|
const debug = (0, debug_1.default)("engine:polling");
|
||||||
|
const compressionMethods = {
|
||||||
|
gzip: zlib_1.createGzip,
|
||||||
|
deflate: zlib_1.createDeflate,
|
||||||
|
};
|
||||||
|
class Polling extends transport_1.Transport {
|
||||||
|
/**
|
||||||
|
* HTTP polling constructor.
|
||||||
|
*/
|
||||||
|
constructor(req) {
|
||||||
|
super(req);
|
||||||
|
this.closeTimeout = 30 * 1000;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Transport name
|
||||||
|
*/
|
||||||
|
get name() {
|
||||||
|
return "polling";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Overrides onRequest.
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
* @package
|
||||||
|
*/
|
||||||
|
onRequest(req) {
|
||||||
|
const res = req.res;
|
||||||
|
// remove the reference to the ServerResponse object (as the first request of the session is kept in memory by default)
|
||||||
|
req.res = null;
|
||||||
|
if ("GET" === req.method) {
|
||||||
|
this.onPollRequest(req, res);
|
||||||
|
}
|
||||||
|
else if ("POST" === req.method) {
|
||||||
|
this.onDataRequest(req, res);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res.writeHead(500);
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The client sends a request awaiting for us to send data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onPollRequest(req, res) {
|
||||||
|
if (this.req) {
|
||||||
|
debug("request overlap");
|
||||||
|
// assert: this.res, '.req and .res should be (un)set together'
|
||||||
|
this.onError("overlap from client");
|
||||||
|
res.writeHead(400);
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug("setting request");
|
||||||
|
this.req = req;
|
||||||
|
this.res = res;
|
||||||
|
const onClose = () => {
|
||||||
|
this.onError("poll connection closed prematurely");
|
||||||
|
};
|
||||||
|
const cleanup = () => {
|
||||||
|
req.removeListener("close", onClose);
|
||||||
|
this.req = this.res = null;
|
||||||
|
};
|
||||||
|
req.cleanup = cleanup;
|
||||||
|
req.on("close", onClose);
|
||||||
|
this.writable = true;
|
||||||
|
this.emit("ready");
|
||||||
|
// if we're still writable but had a pending close, trigger an empty send
|
||||||
|
if (this.writable && this.shouldClose) {
|
||||||
|
debug("triggering empty send to append close packet");
|
||||||
|
this.send([{ type: "noop" }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The client sends a request with data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onDataRequest(req, res) {
|
||||||
|
if (this.dataReq) {
|
||||||
|
// assert: this.dataRes, '.dataReq and .dataRes should be (un)set together'
|
||||||
|
this.onError("data request overlap from client");
|
||||||
|
res.writeHead(400);
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const isBinary = "application/octet-stream" === req.headers["content-type"];
|
||||||
|
if (isBinary && this.protocol === 4) {
|
||||||
|
return this.onError("invalid content");
|
||||||
|
}
|
||||||
|
this.dataReq = req;
|
||||||
|
this.dataRes = res;
|
||||||
|
let chunks = isBinary ? Buffer.concat([]) : "";
|
||||||
|
const cleanup = () => {
|
||||||
|
req.removeListener("data", onData);
|
||||||
|
req.removeListener("end", onEnd);
|
||||||
|
req.removeListener("close", onClose);
|
||||||
|
this.dataReq = this.dataRes = chunks = null;
|
||||||
|
};
|
||||||
|
const onClose = () => {
|
||||||
|
cleanup();
|
||||||
|
this.onError("data request connection closed prematurely");
|
||||||
|
};
|
||||||
|
const onData = (data) => {
|
||||||
|
let contentLength;
|
||||||
|
if (isBinary) {
|
||||||
|
chunks = Buffer.concat([chunks, data]);
|
||||||
|
contentLength = chunks.length;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chunks += data;
|
||||||
|
contentLength = Buffer.byteLength(chunks);
|
||||||
|
}
|
||||||
|
if (contentLength > this.maxHttpBufferSize) {
|
||||||
|
res.writeHead(413).end();
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onEnd = () => {
|
||||||
|
this.onData(chunks);
|
||||||
|
const headers = {
|
||||||
|
// text/html is required instead of text/plain to avoid an
|
||||||
|
// unwanted download dialog on certain user-agents (GH-43)
|
||||||
|
"Content-Type": "text/html",
|
||||||
|
"Content-Length": "2",
|
||||||
|
};
|
||||||
|
res.writeHead(200, this.headers(req, headers));
|
||||||
|
res.end("ok");
|
||||||
|
cleanup();
|
||||||
|
};
|
||||||
|
req.on("close", onClose);
|
||||||
|
if (!isBinary)
|
||||||
|
req.setEncoding("utf8");
|
||||||
|
req.on("data", onData);
|
||||||
|
req.on("end", onEnd);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Processes the incoming data payload.
|
||||||
|
*
|
||||||
|
* @param data - encoded payload
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
onData(data) {
|
||||||
|
debug('received "%s"', data);
|
||||||
|
const callback = (packet) => {
|
||||||
|
if ("close" === packet.type) {
|
||||||
|
debug("got xhr close packet");
|
||||||
|
this.onClose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.onPacket(packet);
|
||||||
|
};
|
||||||
|
if (this.protocol === 3) {
|
||||||
|
this.parser.decodePayload(data, callback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.parser.decodePayload(data).forEach(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Overrides onClose.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onClose() {
|
||||||
|
if (this.writable) {
|
||||||
|
// close pending poll request
|
||||||
|
this.send([{ type: "noop" }]);
|
||||||
|
}
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
|
send(packets) {
|
||||||
|
this.writable = false;
|
||||||
|
if (this.shouldClose) {
|
||||||
|
debug("appending close packet to payload");
|
||||||
|
packets.push({ type: "close" });
|
||||||
|
this.shouldClose();
|
||||||
|
this.shouldClose = null;
|
||||||
|
}
|
||||||
|
const doWrite = (data) => {
|
||||||
|
const compress = packets.some((packet) => {
|
||||||
|
return packet.options && packet.options.compress;
|
||||||
|
});
|
||||||
|
this.write(data, { compress });
|
||||||
|
};
|
||||||
|
if (this.protocol === 3) {
|
||||||
|
this.parser.encodePayload(packets, this.supportsBinary, doWrite);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.parser.encodePayload(packets, doWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes data as response to poll request.
|
||||||
|
*
|
||||||
|
* @param {String} data
|
||||||
|
* @param {Object} options
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
write(data, options) {
|
||||||
|
debug('writing "%s"', data);
|
||||||
|
this.doWrite(data, options, () => {
|
||||||
|
this.req.cleanup();
|
||||||
|
this.emit("drain");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Performs the write.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
doWrite(data, options, callback) {
|
||||||
|
// explicit UTF-8 is required for pages not served under utf
|
||||||
|
const isString = typeof data === "string";
|
||||||
|
const contentType = isString
|
||||||
|
? "text/plain; charset=UTF-8"
|
||||||
|
: "application/octet-stream";
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": contentType,
|
||||||
|
};
|
||||||
|
const respond = (data) => {
|
||||||
|
headers["Content-Length"] =
|
||||||
|
"string" === typeof data ? Buffer.byteLength(data) : data.length;
|
||||||
|
this.res.writeHead(200, this.headers(this.req, headers));
|
||||||
|
this.res.end(data);
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
if (!this.httpCompression || !options.compress) {
|
||||||
|
respond(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const len = isString ? Buffer.byteLength(data) : data.length;
|
||||||
|
if (len < this.httpCompression.threshold) {
|
||||||
|
respond(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const encoding = accepts(this.req).encodings(["gzip", "deflate"]);
|
||||||
|
if (!encoding) {
|
||||||
|
respond(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.compress(data, encoding, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
this.res.writeHead(500);
|
||||||
|
this.res.end();
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
headers["Content-Encoding"] = encoding;
|
||||||
|
respond(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Compresses data.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
compress(data, encoding, callback) {
|
||||||
|
debug("compressing");
|
||||||
|
const buffers = [];
|
||||||
|
let nread = 0;
|
||||||
|
compressionMethods[encoding](this.httpCompression)
|
||||||
|
.on("error", callback)
|
||||||
|
.on("data", function (chunk) {
|
||||||
|
buffers.push(chunk);
|
||||||
|
nread += chunk.length;
|
||||||
|
})
|
||||||
|
.on("end", function () {
|
||||||
|
callback(null, Buffer.concat(buffers, nread));
|
||||||
|
})
|
||||||
|
.end(data);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Closes the transport.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
doClose(fn) {
|
||||||
|
debug("closing");
|
||||||
|
let closeTimeoutTimer;
|
||||||
|
if (this.dataReq) {
|
||||||
|
debug("aborting ongoing data request");
|
||||||
|
this.dataReq.destroy();
|
||||||
|
}
|
||||||
|
const onClose = () => {
|
||||||
|
clearTimeout(closeTimeoutTimer);
|
||||||
|
fn();
|
||||||
|
this.onClose();
|
||||||
|
};
|
||||||
|
if (this.writable) {
|
||||||
|
debug("transport writable - closing right away");
|
||||||
|
this.send([{ type: "close" }]);
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
else if (this.discarded) {
|
||||||
|
debug("transport discarded - closing right away");
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("transport not writable - buffering orderly close");
|
||||||
|
this.shouldClose = onClose;
|
||||||
|
closeTimeoutTimer = setTimeout(onClose, this.closeTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns headers for a response.
|
||||||
|
*
|
||||||
|
* @param {http.IncomingMessage} req
|
||||||
|
* @param {Object} headers - extra headers
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
headers(req, headers = {}) {
|
||||||
|
// prevent XSS warnings on IE
|
||||||
|
// https://github.com/LearnBoost/socket.io/pull/1333
|
||||||
|
const ua = req.headers["user-agent"];
|
||||||
|
if (ua && (~ua.indexOf(";MSIE") || ~ua.indexOf("Trident/"))) {
|
||||||
|
headers["X-XSS-Protection"] = "0";
|
||||||
|
}
|
||||||
|
headers["cache-control"] = "no-store";
|
||||||
|
this.emit("headers", headers, req);
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Polling = Polling;
|
||||||
33
node_modules/engine.io/build/transports/websocket.d.ts
generated
vendored
Normal file
33
node_modules/engine.io/build/transports/websocket.d.ts
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { EngineRequest, Transport } from "../transport";
|
||||||
|
import type { Packet } from "engine.io-parser";
|
||||||
|
import type { PerMessageDeflateOptions } from "ws";
|
||||||
|
export declare class WebSocket extends Transport {
|
||||||
|
perMessageDeflate?: boolean | PerMessageDeflateOptions;
|
||||||
|
private socket;
|
||||||
|
/**
|
||||||
|
* WebSocket transport
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
*/
|
||||||
|
constructor(req: EngineRequest);
|
||||||
|
/**
|
||||||
|
* Transport name
|
||||||
|
*/
|
||||||
|
get name(): string;
|
||||||
|
/**
|
||||||
|
* Advertise upgrade support.
|
||||||
|
*/
|
||||||
|
get handlesUpgrades(): boolean;
|
||||||
|
send(packets: Packet[]): void;
|
||||||
|
/**
|
||||||
|
* Whether the encoding of the WebSocket frame can be skipped.
|
||||||
|
* @param packet
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _canSendPreEncodedFrame;
|
||||||
|
private _doSend;
|
||||||
|
private _doSendLast;
|
||||||
|
private _onSent;
|
||||||
|
private _onSentLast;
|
||||||
|
doClose(fn?: () => void): void;
|
||||||
|
}
|
||||||
93
node_modules/engine.io/build/transports/websocket.js
generated
vendored
Normal file
93
node_modules/engine.io/build/transports/websocket.js
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.WebSocket = void 0;
|
||||||
|
const transport_1 = require("../transport");
|
||||||
|
const debug_1 = require("debug");
|
||||||
|
const debug = (0, debug_1.default)("engine:ws");
|
||||||
|
class WebSocket extends transport_1.Transport {
|
||||||
|
/**
|
||||||
|
* WebSocket transport
|
||||||
|
*
|
||||||
|
* @param {EngineRequest} req
|
||||||
|
*/
|
||||||
|
constructor(req) {
|
||||||
|
super(req);
|
||||||
|
this._doSend = (data) => {
|
||||||
|
this.socket.send(data, this._onSent);
|
||||||
|
};
|
||||||
|
this._doSendLast = (data) => {
|
||||||
|
this.socket.send(data, this._onSentLast);
|
||||||
|
};
|
||||||
|
this._onSent = (err) => {
|
||||||
|
if (err) {
|
||||||
|
this.onError("write error", err.stack);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this._onSentLast = (err) => {
|
||||||
|
if (err) {
|
||||||
|
this.onError("write error", err.stack);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.emit("drain");
|
||||||
|
this.writable = true;
|
||||||
|
this.emit("ready");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.socket = req.websocket;
|
||||||
|
this.socket.on("message", (data, isBinary) => {
|
||||||
|
const message = isBinary ? data : data.toString();
|
||||||
|
debug('received "%s"', message);
|
||||||
|
super.onData(message);
|
||||||
|
});
|
||||||
|
this.socket.once("close", this.onClose.bind(this));
|
||||||
|
this.socket.on("error", this.onError.bind(this));
|
||||||
|
this.writable = true;
|
||||||
|
this.perMessageDeflate = null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Transport name
|
||||||
|
*/
|
||||||
|
get name() {
|
||||||
|
return "websocket";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Advertise upgrade support.
|
||||||
|
*/
|
||||||
|
get handlesUpgrades() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
send(packets) {
|
||||||
|
this.writable = false;
|
||||||
|
for (let i = 0; i < packets.length; i++) {
|
||||||
|
const packet = packets[i];
|
||||||
|
const isLast = i + 1 === packets.length;
|
||||||
|
if (this._canSendPreEncodedFrame(packet)) {
|
||||||
|
// the WebSocket frame was computed with WebSocket.Sender.frame()
|
||||||
|
// see https://github.com/websockets/ws/issues/617#issuecomment-283002469
|
||||||
|
// @ts-expect-error use of untyped member
|
||||||
|
this.socket._sender.sendFrame(packet.options.wsPreEncodedFrame, isLast ? this._onSentLast : this._onSent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.parser.encodePacket(packet, this.supportsBinary, isLast ? this._doSendLast : this._doSend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Whether the encoding of the WebSocket frame can be skipped.
|
||||||
|
* @param packet
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_canSendPreEncodedFrame(packet) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
return (!this.perMessageDeflate &&
|
||||||
|
// @ts-expect-error use of untyped member
|
||||||
|
typeof ((_b = (_a = this.socket) === null || _a === void 0 ? void 0 : _a._sender) === null || _b === void 0 ? void 0 : _b.sendFrame) === "function" &&
|
||||||
|
((_c = packet.options) === null || _c === void 0 ? void 0 : _c.wsPreEncodedFrame) !== undefined);
|
||||||
|
}
|
||||||
|
doClose(fn) {
|
||||||
|
debug("closing");
|
||||||
|
this.socket.close();
|
||||||
|
fn && fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.WebSocket = WebSocket;
|
||||||
12
node_modules/engine.io/build/transports/webtransport.d.ts
generated
vendored
Normal file
12
node_modules/engine.io/build/transports/webtransport.d.ts
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Transport } from "../transport";
|
||||||
|
/**
|
||||||
|
* Reference: https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API
|
||||||
|
*/
|
||||||
|
export declare class WebTransport extends Transport {
|
||||||
|
private readonly session;
|
||||||
|
private readonly writer;
|
||||||
|
constructor(session: any, stream: any, reader: any);
|
||||||
|
get name(): string;
|
||||||
|
send(packets: any): Promise<void>;
|
||||||
|
doClose(fn: any): void;
|
||||||
|
}
|
||||||
63
node_modules/engine.io/build/transports/webtransport.js
generated
vendored
Normal file
63
node_modules/engine.io/build/transports/webtransport.js
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.WebTransport = void 0;
|
||||||
|
const transport_1 = require("../transport");
|
||||||
|
const debug_1 = require("debug");
|
||||||
|
const engine_io_parser_1 = require("engine.io-parser");
|
||||||
|
const debug = (0, debug_1.default)("engine:webtransport");
|
||||||
|
/**
|
||||||
|
* Reference: https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API
|
||||||
|
*/
|
||||||
|
class WebTransport extends transport_1.Transport {
|
||||||
|
constructor(session, stream, reader) {
|
||||||
|
super({ _query: { EIO: "4" } });
|
||||||
|
this.session = session;
|
||||||
|
const transformStream = (0, engine_io_parser_1.createPacketEncoderStream)();
|
||||||
|
transformStream.readable.pipeTo(stream.writable).catch(() => {
|
||||||
|
debug("the stream was closed");
|
||||||
|
});
|
||||||
|
this.writer = transformStream.writable.getWriter();
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
const { value, done } = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
debug("session is closed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug("received chunk: %o", value);
|
||||||
|
this.onPacket(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
debug("error while reading: %s", e.message);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
session.closed.then(() => this.onClose());
|
||||||
|
this.writable = true;
|
||||||
|
}
|
||||||
|
get name() {
|
||||||
|
return "webtransport";
|
||||||
|
}
|
||||||
|
async send(packets) {
|
||||||
|
this.writable = false;
|
||||||
|
try {
|
||||||
|
for (let i = 0; i < packets.length; i++) {
|
||||||
|
const packet = packets[i];
|
||||||
|
await this.writer.write(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
debug("error while writing: %s", e.message);
|
||||||
|
}
|
||||||
|
this.emit("drain");
|
||||||
|
this.writable = true;
|
||||||
|
this.emit("ready");
|
||||||
|
}
|
||||||
|
doClose(fn) {
|
||||||
|
debug("closing WebTransport session");
|
||||||
|
this.session.close();
|
||||||
|
fn && fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.WebTransport = WebTransport;
|
||||||
43
node_modules/engine.io/build/userver.d.ts
generated
vendored
Normal file
43
node_modules/engine.io/build/userver.d.ts
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { AttachOptions, BaseServer } from "./server";
|
||||||
|
import { EngineRequest } from "./transport";
|
||||||
|
export interface uOptions {
|
||||||
|
/**
|
||||||
|
* What permessage-deflate compression to use. uWS.DISABLED, uWS.SHARED_COMPRESSOR or any of the uWS.DEDICATED_COMPRESSOR_xxxKB.
|
||||||
|
* @default uWS.DISABLED
|
||||||
|
*/
|
||||||
|
compression?: number;
|
||||||
|
/**
|
||||||
|
* Maximum amount of seconds that may pass without sending or getting a message. Connection is closed if this timeout passes. Resolution (granularity) for timeouts are typically 4 seconds, rounded to closest. Disable by using 0.
|
||||||
|
* @default 120
|
||||||
|
*/
|
||||||
|
idleTimeout?: number;
|
||||||
|
/**
|
||||||
|
* Maximum length of allowed backpressure per socket when publishing or sending messages. Slow receivers with too high backpressure will be skipped until they catch up or timeout.
|
||||||
|
* @default 1024 * 1024
|
||||||
|
*/
|
||||||
|
maxBackpressure?: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* An Engine.IO server based on the `uWebSockets.js` package.
|
||||||
|
*/
|
||||||
|
export declare class uServer extends BaseServer {
|
||||||
|
protected init(): void;
|
||||||
|
protected cleanup(): void;
|
||||||
|
/**
|
||||||
|
* Prepares a request by processing the query string.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private prepare;
|
||||||
|
protected createTransport(transportName: string, req: EngineRequest): any;
|
||||||
|
/**
|
||||||
|
* Attach the engine to a µWebSockets.js server
|
||||||
|
* @param app
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
attach(app: any, options?: AttachOptions & uOptions): void;
|
||||||
|
_applyMiddlewares(req: any, res: any, callback: (err?: any) => void): void;
|
||||||
|
private handleRequest;
|
||||||
|
private handleUpgrade;
|
||||||
|
private abortRequest;
|
||||||
|
}
|
||||||
290
node_modules/engine.io/build/userver.js
generated
vendored
Normal file
290
node_modules/engine.io/build/userver.js
generated
vendored
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.uServer = void 0;
|
||||||
|
const debug_1 = require("debug");
|
||||||
|
const server_1 = require("./server");
|
||||||
|
const transports_uws_1 = require("./transports-uws");
|
||||||
|
const debug = (0, debug_1.default)("engine:uws");
|
||||||
|
/**
|
||||||
|
* An Engine.IO server based on the `uWebSockets.js` package.
|
||||||
|
*/
|
||||||
|
// TODO export it into its own package
|
||||||
|
class uServer extends server_1.BaseServer {
|
||||||
|
init() { }
|
||||||
|
cleanup() { }
|
||||||
|
/**
|
||||||
|
* Prepares a request by processing the query string.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
prepare(req, res) {
|
||||||
|
req.method = req.getMethod().toUpperCase();
|
||||||
|
req.url = req.getUrl();
|
||||||
|
const params = new URLSearchParams(req.getQuery());
|
||||||
|
req._query = Object.fromEntries(params.entries());
|
||||||
|
req.headers = {};
|
||||||
|
req.forEach((key, value) => {
|
||||||
|
req.headers[key] = value;
|
||||||
|
});
|
||||||
|
// @ts-expect-error
|
||||||
|
req.connection = {
|
||||||
|
remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString(),
|
||||||
|
};
|
||||||
|
res.onAborted(() => {
|
||||||
|
debug("response has been aborted");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
createTransport(transportName, req) {
|
||||||
|
return new transports_uws_1.default[transportName](req);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Attach the engine to a µWebSockets.js server
|
||||||
|
* @param app
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
attach(app /* : TemplatedApp */, options = {}) {
|
||||||
|
const path = this._computePath(options);
|
||||||
|
app
|
||||||
|
.any(path, this.handleRequest.bind(this))
|
||||||
|
//
|
||||||
|
.ws(path, {
|
||||||
|
compression: options.compression,
|
||||||
|
idleTimeout: options.idleTimeout,
|
||||||
|
maxBackpressure: options.maxBackpressure,
|
||||||
|
maxPayloadLength: this.opts.maxHttpBufferSize,
|
||||||
|
upgrade: this.handleUpgrade.bind(this),
|
||||||
|
open: (ws) => {
|
||||||
|
const transport = ws.getUserData().transport;
|
||||||
|
transport.socket = ws;
|
||||||
|
transport.writable = true;
|
||||||
|
transport.emit("ready");
|
||||||
|
},
|
||||||
|
message: (ws, message, isBinary) => {
|
||||||
|
ws.getUserData().transport.onData(isBinary ? message : Buffer.from(message).toString());
|
||||||
|
},
|
||||||
|
close: (ws, code, message) => {
|
||||||
|
ws.getUserData().transport.onClose(code, message);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_applyMiddlewares(req, res, callback) {
|
||||||
|
if (this.middlewares.length === 0) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
// needed to buffer headers until the status is computed
|
||||||
|
req.res = new ResponseWrapper(res);
|
||||||
|
super._applyMiddlewares(req, req.res, (err) => {
|
||||||
|
// some middlewares (like express-session) wait for the writeHead() call to flush their headers
|
||||||
|
// see https://github.com/expressjs/session/blob/1010fadc2f071ddf2add94235d72224cf65159c6/index.js#L220-L244
|
||||||
|
req.res.writeHead();
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
handleRequest(res, req) {
|
||||||
|
debug('handling "%s" http request "%s"', req.getMethod(), req.getUrl());
|
||||||
|
this.prepare(req, res);
|
||||||
|
req.res = res;
|
||||||
|
const callback = (errorCode, errorContext) => {
|
||||||
|
if (errorCode !== undefined) {
|
||||||
|
this.emit("connection_error", {
|
||||||
|
req,
|
||||||
|
code: errorCode,
|
||||||
|
message: server_1.Server.errorMessages[errorCode],
|
||||||
|
context: errorContext,
|
||||||
|
});
|
||||||
|
this.abortRequest(req.res, errorCode, errorContext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (req._query.sid) {
|
||||||
|
debug("setting new request for existing client");
|
||||||
|
// @ts-ignore
|
||||||
|
this.clients[req._query.sid].transport.onRequest(req);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const closeConnection = (errorCode, errorContext) => this.abortRequest(res, errorCode, errorContext);
|
||||||
|
this.handshake(req._query.transport, req, closeConnection);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this._applyMiddlewares(req, res, (err) => {
|
||||||
|
if (err) {
|
||||||
|
callback(server_1.Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.verify(req, false, callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
handleUpgrade(res, req, context) {
|
||||||
|
debug("on upgrade");
|
||||||
|
this.prepare(req, res);
|
||||||
|
req.res = res;
|
||||||
|
const callback = async (errorCode, errorContext) => {
|
||||||
|
if (errorCode !== undefined) {
|
||||||
|
this.emit("connection_error", {
|
||||||
|
req,
|
||||||
|
code: errorCode,
|
||||||
|
message: server_1.Server.errorMessages[errorCode],
|
||||||
|
context: errorContext,
|
||||||
|
});
|
||||||
|
this.abortRequest(res, errorCode, errorContext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const id = req._query.sid;
|
||||||
|
let transport;
|
||||||
|
if (id) {
|
||||||
|
const client = this.clients[id];
|
||||||
|
if (!client) {
|
||||||
|
debug("upgrade attempt for closed client");
|
||||||
|
return res.close();
|
||||||
|
}
|
||||||
|
else if (client.upgrading) {
|
||||||
|
debug("transport has already been trying to upgrade");
|
||||||
|
return res.close();
|
||||||
|
}
|
||||||
|
else if (client.upgraded) {
|
||||||
|
debug("transport had already been upgraded");
|
||||||
|
return res.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug("upgrading existing transport");
|
||||||
|
transport = this.createTransport(req._query.transport, req);
|
||||||
|
client._maybeUpgrade(transport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
transport = await this.handshake(req._query.transport, req, (errorCode, errorContext) => this.abortRequest(res, errorCode, errorContext));
|
||||||
|
if (!transport) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// emit headers events for WebSocket upgrades
|
||||||
|
const additionalHeaders = {};
|
||||||
|
const isInitialRequest = !id;
|
||||||
|
if (isInitialRequest) {
|
||||||
|
this.emit("initial_headers", additionalHeaders, req);
|
||||||
|
}
|
||||||
|
this.emit("headers", additionalHeaders, req);
|
||||||
|
// calling writeStatus() triggers the flushing of any header added in a middleware
|
||||||
|
req.res.writeStatus("101 Switching Protocols");
|
||||||
|
Object.keys(additionalHeaders).forEach((key) => {
|
||||||
|
req.res.writeHeader(key, additionalHeaders[key]);
|
||||||
|
});
|
||||||
|
res.upgrade({
|
||||||
|
transport,
|
||||||
|
}, req.getHeader("sec-websocket-key"), req.getHeader("sec-websocket-protocol"), req.getHeader("sec-websocket-extensions"), context);
|
||||||
|
};
|
||||||
|
this._applyMiddlewares(req, res, (err) => {
|
||||||
|
if (err) {
|
||||||
|
callback(server_1.Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.verify(req, true, callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
abortRequest(res, errorCode, errorContext) {
|
||||||
|
const statusCode = errorCode === server_1.Server.errors.FORBIDDEN
|
||||||
|
? "403 Forbidden"
|
||||||
|
: "400 Bad Request";
|
||||||
|
const message = errorContext && errorContext.message
|
||||||
|
? errorContext.message
|
||||||
|
: server_1.Server.errorMessages[errorCode];
|
||||||
|
res.writeStatus(statusCode);
|
||||||
|
res.writeHeader("Content-Type", "application/json");
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
code: errorCode,
|
||||||
|
message,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.uServer = uServer;
|
||||||
|
class ResponseWrapper {
|
||||||
|
constructor(res) {
|
||||||
|
this.res = res;
|
||||||
|
this.statusWritten = false;
|
||||||
|
this.headers = [];
|
||||||
|
this.isAborted = false;
|
||||||
|
}
|
||||||
|
set statusCode(status) {
|
||||||
|
if (!status) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// FIXME: handle all status codes?
|
||||||
|
this.writeStatus(status === 200 ? "200 OK" : "204 No Content");
|
||||||
|
}
|
||||||
|
writeHead(status) {
|
||||||
|
this.statusCode = status;
|
||||||
|
}
|
||||||
|
setHeader(key, value) {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value.forEach((val) => {
|
||||||
|
this.writeHeader(key, val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.writeHeader(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeHeader() {
|
||||||
|
// FIXME: not implemented
|
||||||
|
}
|
||||||
|
// needed by vary: https://github.com/jshttp/vary/blob/5d725d059b3871025cf753e9dfa08924d0bcfa8f/index.js#L134
|
||||||
|
getHeader() { }
|
||||||
|
writeStatus(status) {
|
||||||
|
if (this.isAborted)
|
||||||
|
return;
|
||||||
|
this.res.writeStatus(status);
|
||||||
|
this.statusWritten = true;
|
||||||
|
this.writeBufferedHeaders();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
writeHeader(key, value) {
|
||||||
|
if (this.isAborted)
|
||||||
|
return;
|
||||||
|
if (key === "Content-Length") {
|
||||||
|
// the content length is automatically added by uWebSockets.js
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.statusWritten) {
|
||||||
|
this.res.writeHeader(key, value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.headers.push([key, value]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeBufferedHeaders() {
|
||||||
|
this.headers.forEach(([key, value]) => {
|
||||||
|
this.res.writeHeader(key, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
end(data) {
|
||||||
|
if (this.isAborted)
|
||||||
|
return;
|
||||||
|
this.res.cork(() => {
|
||||||
|
if (!this.statusWritten) {
|
||||||
|
// status will be inferred as "200 OK"
|
||||||
|
this.writeBufferedHeaders();
|
||||||
|
}
|
||||||
|
this.res.end(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onData(fn) {
|
||||||
|
if (this.isAborted)
|
||||||
|
return;
|
||||||
|
this.res.onData(fn);
|
||||||
|
}
|
||||||
|
onAborted(fn) {
|
||||||
|
if (this.isAborted)
|
||||||
|
return;
|
||||||
|
this.res.onAborted(() => {
|
||||||
|
// Any attempt to use the UWS response object after abort will throw!
|
||||||
|
this.isAborted = true;
|
||||||
|
fn();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cork(fn) {
|
||||||
|
if (this.isAborted)
|
||||||
|
return;
|
||||||
|
this.res.cork(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
243
node_modules/engine.io/node_modules/accepts/HISTORY.md
generated
vendored
Normal file
243
node_modules/engine.io/node_modules/accepts/HISTORY.md
generated
vendored
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
1.3.8 / 2022-02-02
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.34
|
||||||
|
- deps: mime-db@~1.51.0
|
||||||
|
* deps: negotiator@0.6.3
|
||||||
|
|
||||||
|
1.3.7 / 2019-04-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.6.2
|
||||||
|
- Fix sorting charset, encoding, and language with extra parameters
|
||||||
|
|
||||||
|
1.3.6 / 2019-04-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.24
|
||||||
|
- deps: mime-db@~1.40.0
|
||||||
|
|
||||||
|
1.3.5 / 2018-02-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.18
|
||||||
|
- deps: mime-db@~1.33.0
|
||||||
|
|
||||||
|
1.3.4 / 2017-08-22
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.16
|
||||||
|
- deps: mime-db@~1.29.0
|
||||||
|
|
||||||
|
1.3.3 / 2016-05-02
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.11
|
||||||
|
- deps: mime-db@~1.23.0
|
||||||
|
* deps: negotiator@0.6.1
|
||||||
|
- perf: improve `Accept` parsing speed
|
||||||
|
- perf: improve `Accept-Charset` parsing speed
|
||||||
|
- perf: improve `Accept-Encoding` parsing speed
|
||||||
|
- perf: improve `Accept-Language` parsing speed
|
||||||
|
|
||||||
|
1.3.2 / 2016-03-08
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.10
|
||||||
|
- Fix extension of `application/dash+xml`
|
||||||
|
- Update primary extension for `audio/mp4`
|
||||||
|
- deps: mime-db@~1.22.0
|
||||||
|
|
||||||
|
1.3.1 / 2016-01-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.9
|
||||||
|
- deps: mime-db@~1.21.0
|
||||||
|
|
||||||
|
1.3.0 / 2015-09-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.7
|
||||||
|
- deps: mime-db@~1.19.0
|
||||||
|
* deps: negotiator@0.6.0
|
||||||
|
- Fix including type extensions in parameters in `Accept` parsing
|
||||||
|
- Fix parsing `Accept` parameters with quoted equals
|
||||||
|
- Fix parsing `Accept` parameters with quoted semicolons
|
||||||
|
- Lazy-load modules from main entry point
|
||||||
|
- perf: delay type concatenation until needed
|
||||||
|
- perf: enable strict mode
|
||||||
|
- perf: hoist regular expressions
|
||||||
|
- perf: remove closures getting spec properties
|
||||||
|
- perf: remove a closure from media type parsing
|
||||||
|
- perf: remove property delete from media type parsing
|
||||||
|
|
||||||
|
1.2.13 / 2015-09-06
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.6
|
||||||
|
- deps: mime-db@~1.18.0
|
||||||
|
|
||||||
|
1.2.12 / 2015-07-30
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.4
|
||||||
|
- deps: mime-db@~1.16.0
|
||||||
|
|
||||||
|
1.2.11 / 2015-07-16
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.3
|
||||||
|
- deps: mime-db@~1.15.0
|
||||||
|
|
||||||
|
1.2.10 / 2015-07-01
|
||||||
|
===================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.2
|
||||||
|
- deps: mime-db@~1.14.0
|
||||||
|
|
||||||
|
1.2.9 / 2015-06-08
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.1
|
||||||
|
- perf: fix deopt during mapping
|
||||||
|
|
||||||
|
1.2.8 / 2015-06-07
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.1.0
|
||||||
|
- deps: mime-db@~1.13.0
|
||||||
|
* perf: avoid argument reassignment & argument slice
|
||||||
|
* perf: avoid negotiator recursive construction
|
||||||
|
* perf: enable strict mode
|
||||||
|
* perf: remove unnecessary bitwise operator
|
||||||
|
|
||||||
|
1.2.7 / 2015-05-10
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.5.3
|
||||||
|
- Fix media type parameter matching to be case-insensitive
|
||||||
|
|
||||||
|
1.2.6 / 2015-05-07
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.11
|
||||||
|
- deps: mime-db@~1.9.1
|
||||||
|
* deps: negotiator@0.5.2
|
||||||
|
- Fix comparing media types with quoted values
|
||||||
|
- Fix splitting media types with quoted commas
|
||||||
|
|
||||||
|
1.2.5 / 2015-03-13
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.10
|
||||||
|
- deps: mime-db@~1.8.0
|
||||||
|
|
||||||
|
1.2.4 / 2015-02-14
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Support Node.js 0.6
|
||||||
|
* deps: mime-types@~2.0.9
|
||||||
|
- deps: mime-db@~1.7.0
|
||||||
|
* deps: negotiator@0.5.1
|
||||||
|
- Fix preference sorting to be stable for long acceptable lists
|
||||||
|
|
||||||
|
1.2.3 / 2015-01-31
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.8
|
||||||
|
- deps: mime-db@~1.6.0
|
||||||
|
|
||||||
|
1.2.2 / 2014-12-30
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.7
|
||||||
|
- deps: mime-db@~1.5.0
|
||||||
|
|
||||||
|
1.2.1 / 2014-12-30
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.5
|
||||||
|
- deps: mime-db@~1.3.1
|
||||||
|
|
||||||
|
1.2.0 / 2014-12-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.5.0
|
||||||
|
- Fix list return order when large accepted list
|
||||||
|
- Fix missing identity encoding when q=0 exists
|
||||||
|
- Remove dynamic building of Negotiator class
|
||||||
|
|
||||||
|
1.1.4 / 2014-12-10
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.4
|
||||||
|
- deps: mime-db@~1.3.0
|
||||||
|
|
||||||
|
1.1.3 / 2014-11-09
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.3
|
||||||
|
- deps: mime-db@~1.2.0
|
||||||
|
|
||||||
|
1.1.2 / 2014-10-14
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.4.9
|
||||||
|
- Fix error when media type has invalid parameter
|
||||||
|
|
||||||
|
1.1.1 / 2014-09-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: mime-types@~2.0.2
|
||||||
|
- deps: mime-db@~1.1.0
|
||||||
|
* deps: negotiator@0.4.8
|
||||||
|
- Fix all negotiations to be case-insensitive
|
||||||
|
- Stable sort preferences of same quality according to client order
|
||||||
|
|
||||||
|
1.1.0 / 2014-09-02
|
||||||
|
==================
|
||||||
|
|
||||||
|
* update `mime-types`
|
||||||
|
|
||||||
|
1.0.7 / 2014-07-04
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix wrong type returned from `type` when match after unknown extension
|
||||||
|
|
||||||
|
1.0.6 / 2014-06-24
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.4.7
|
||||||
|
|
||||||
|
1.0.5 / 2014-06-20
|
||||||
|
==================
|
||||||
|
|
||||||
|
* fix crash when unknown extension given
|
||||||
|
|
||||||
|
1.0.4 / 2014-06-19
|
||||||
|
==================
|
||||||
|
|
||||||
|
* use `mime-types`
|
||||||
|
|
||||||
|
1.0.3 / 2014-06-11
|
||||||
|
==================
|
||||||
|
|
||||||
|
* deps: negotiator@0.4.6
|
||||||
|
- Order by specificity when quality is the same
|
||||||
|
|
||||||
|
1.0.2 / 2014-05-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix interpretation when header not in request
|
||||||
|
* deps: pin negotiator@0.4.5
|
||||||
|
|
||||||
|
1.0.1 / 2014-01-18
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Identity encoding isn't always acceptable
|
||||||
|
* deps: negotiator@~0.4.0
|
||||||
|
|
||||||
|
1.0.0 / 2013-12-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Genesis
|
||||||
23
node_modules/engine.io/node_modules/accepts/LICENSE
generated
vendored
Normal file
23
node_modules/engine.io/node_modules/accepts/LICENSE
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
|
||||||
|
Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
140
node_modules/engine.io/node_modules/accepts/README.md
generated
vendored
Normal file
140
node_modules/engine.io/node_modules/accepts/README.md
generated
vendored
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
# accepts
|
||||||
|
|
||||||
|
[![NPM Version][npm-version-image]][npm-url]
|
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||||
|
[![Node.js Version][node-version-image]][node-version-url]
|
||||||
|
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
|
Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator).
|
||||||
|
Extracted from [koa](https://www.npmjs.com/package/koa) for general use.
|
||||||
|
|
||||||
|
In addition to negotiator, it allows:
|
||||||
|
|
||||||
|
- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])`
|
||||||
|
as well as `('text/html', 'application/json')`.
|
||||||
|
- Allows type shorthands such as `json`.
|
||||||
|
- Returns `false` when no types match
|
||||||
|
- Treats non-existent headers as `*`
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install accepts
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```js
|
||||||
|
var accepts = require('accepts')
|
||||||
|
```
|
||||||
|
|
||||||
|
### accepts(req)
|
||||||
|
|
||||||
|
Create a new `Accepts` object for the given `req`.
|
||||||
|
|
||||||
|
#### .charset(charsets)
|
||||||
|
|
||||||
|
Return the first accepted charset. If nothing in `charsets` is accepted,
|
||||||
|
then `false` is returned.
|
||||||
|
|
||||||
|
#### .charsets()
|
||||||
|
|
||||||
|
Return the charsets that the request accepts, in the order of the client's
|
||||||
|
preference (most preferred first).
|
||||||
|
|
||||||
|
#### .encoding(encodings)
|
||||||
|
|
||||||
|
Return the first accepted encoding. If nothing in `encodings` is accepted,
|
||||||
|
then `false` is returned.
|
||||||
|
|
||||||
|
#### .encodings()
|
||||||
|
|
||||||
|
Return the encodings that the request accepts, in the order of the client's
|
||||||
|
preference (most preferred first).
|
||||||
|
|
||||||
|
#### .language(languages)
|
||||||
|
|
||||||
|
Return the first accepted language. If nothing in `languages` is accepted,
|
||||||
|
then `false` is returned.
|
||||||
|
|
||||||
|
#### .languages()
|
||||||
|
|
||||||
|
Return the languages that the request accepts, in the order of the client's
|
||||||
|
preference (most preferred first).
|
||||||
|
|
||||||
|
#### .type(types)
|
||||||
|
|
||||||
|
Return the first accepted type (and it is returned as the same text as what
|
||||||
|
appears in the `types` array). If nothing in `types` is accepted, then `false`
|
||||||
|
is returned.
|
||||||
|
|
||||||
|
The `types` array can contain full MIME types or file extensions. Any value
|
||||||
|
that is not a full MIME types is passed to `require('mime-types').lookup`.
|
||||||
|
|
||||||
|
#### .types()
|
||||||
|
|
||||||
|
Return the types that the request accepts, in the order of the client's
|
||||||
|
preference (most preferred first).
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Simple type negotiation
|
||||||
|
|
||||||
|
This simple example shows how to use `accepts` to return a different typed
|
||||||
|
respond body based on what the client wants to accept. The server lists it's
|
||||||
|
preferences in order and will get back the best match between the client and
|
||||||
|
server.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var accepts = require('accepts')
|
||||||
|
var http = require('http')
|
||||||
|
|
||||||
|
function app (req, res) {
|
||||||
|
var accept = accepts(req)
|
||||||
|
|
||||||
|
// the order of this list is significant; should be server preferred order
|
||||||
|
switch (accept.type(['json', 'html'])) {
|
||||||
|
case 'json':
|
||||||
|
res.setHeader('Content-Type', 'application/json')
|
||||||
|
res.write('{"hello":"world!"}')
|
||||||
|
break
|
||||||
|
case 'html':
|
||||||
|
res.setHeader('Content-Type', 'text/html')
|
||||||
|
res.write('<b>hello, world!</b>')
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
// the fallback is text/plain, so no need to specify it above
|
||||||
|
res.setHeader('Content-Type', 'text/plain')
|
||||||
|
res.write('hello, world!')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
http.createServer(app).listen(3000)
|
||||||
|
```
|
||||||
|
|
||||||
|
You can test this out with the cURL program:
|
||||||
|
```sh
|
||||||
|
curl -I -H'Accept: text/html' http://localhost:3000/
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
|
|
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master
|
||||||
|
[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master
|
||||||
|
[github-actions-ci-image]: https://badgen.net/github/checks/jshttp/accepts/master?label=ci
|
||||||
|
[github-actions-ci-url]: https://github.com/jshttp/accepts/actions/workflows/ci.yml
|
||||||
|
[node-version-image]: https://badgen.net/npm/node/accepts
|
||||||
|
[node-version-url]: https://nodejs.org/en/download
|
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/accepts
|
||||||
|
[npm-url]: https://npmjs.org/package/accepts
|
||||||
|
[npm-version-image]: https://badgen.net/npm/v/accepts
|
||||||
238
node_modules/engine.io/node_modules/accepts/index.js
generated
vendored
Normal file
238
node_modules/engine.io/node_modules/accepts/index.js
generated
vendored
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/*!
|
||||||
|
* accepts
|
||||||
|
* Copyright(c) 2014 Jonathan Ong
|
||||||
|
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Negotiator = require('negotiator')
|
||||||
|
var mime = require('mime-types')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = Accepts
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Accepts object for the given req.
|
||||||
|
*
|
||||||
|
* @param {object} req
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Accepts (req) {
|
||||||
|
if (!(this instanceof Accepts)) {
|
||||||
|
return new Accepts(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.headers = req.headers
|
||||||
|
this.negotiator = new Negotiator(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given `type(s)` is acceptable, returning
|
||||||
|
* the best match when true, otherwise `undefined`, in which
|
||||||
|
* case you should respond with 406 "Not Acceptable".
|
||||||
|
*
|
||||||
|
* The `type` value may be a single mime type string
|
||||||
|
* such as "application/json", the extension name
|
||||||
|
* such as "json" or an array `["json", "html", "text/plain"]`. When a list
|
||||||
|
* or array is given the _best_ match, if any is returned.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* // Accept: text/html
|
||||||
|
* this.types('html');
|
||||||
|
* // => "html"
|
||||||
|
*
|
||||||
|
* // Accept: text/*, application/json
|
||||||
|
* this.types('html');
|
||||||
|
* // => "html"
|
||||||
|
* this.types('text/html');
|
||||||
|
* // => "text/html"
|
||||||
|
* this.types('json', 'text');
|
||||||
|
* // => "json"
|
||||||
|
* this.types('application/json');
|
||||||
|
* // => "application/json"
|
||||||
|
*
|
||||||
|
* // Accept: text/*, application/json
|
||||||
|
* this.types('image/png');
|
||||||
|
* this.types('png');
|
||||||
|
* // => undefined
|
||||||
|
*
|
||||||
|
* // Accept: text/*;q=.5, application/json
|
||||||
|
* this.types(['html', 'json']);
|
||||||
|
* this.types('html', 'json');
|
||||||
|
* // => "json"
|
||||||
|
*
|
||||||
|
* @param {String|Array} types...
|
||||||
|
* @return {String|Array|Boolean}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Accepts.prototype.type =
|
||||||
|
Accepts.prototype.types = function (types_) {
|
||||||
|
var types = types_
|
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (types && !Array.isArray(types)) {
|
||||||
|
types = new Array(arguments.length)
|
||||||
|
for (var i = 0; i < types.length; i++) {
|
||||||
|
types[i] = arguments[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no types, return all requested types
|
||||||
|
if (!types || types.length === 0) {
|
||||||
|
return this.negotiator.mediaTypes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// no accept header, return first given type
|
||||||
|
if (!this.headers.accept) {
|
||||||
|
return types[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
var mimes = types.map(extToMime)
|
||||||
|
var accepts = this.negotiator.mediaTypes(mimes.filter(validMime))
|
||||||
|
var first = accepts[0]
|
||||||
|
|
||||||
|
return first
|
||||||
|
? types[mimes.indexOf(first)]
|
||||||
|
: false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return accepted encodings or best fit based on `encodings`.
|
||||||
|
*
|
||||||
|
* Given `Accept-Encoding: gzip, deflate`
|
||||||
|
* an array sorted by quality is returned:
|
||||||
|
*
|
||||||
|
* ['gzip', 'deflate']
|
||||||
|
*
|
||||||
|
* @param {String|Array} encodings...
|
||||||
|
* @return {String|Array}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Accepts.prototype.encoding =
|
||||||
|
Accepts.prototype.encodings = function (encodings_) {
|
||||||
|
var encodings = encodings_
|
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (encodings && !Array.isArray(encodings)) {
|
||||||
|
encodings = new Array(arguments.length)
|
||||||
|
for (var i = 0; i < encodings.length; i++) {
|
||||||
|
encodings[i] = arguments[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no encodings, return all requested encodings
|
||||||
|
if (!encodings || encodings.length === 0) {
|
||||||
|
return this.negotiator.encodings()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.negotiator.encodings(encodings)[0] || false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return accepted charsets or best fit based on `charsets`.
|
||||||
|
*
|
||||||
|
* Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
|
||||||
|
* an array sorted by quality is returned:
|
||||||
|
*
|
||||||
|
* ['utf-8', 'utf-7', 'iso-8859-1']
|
||||||
|
*
|
||||||
|
* @param {String|Array} charsets...
|
||||||
|
* @return {String|Array}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Accepts.prototype.charset =
|
||||||
|
Accepts.prototype.charsets = function (charsets_) {
|
||||||
|
var charsets = charsets_
|
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (charsets && !Array.isArray(charsets)) {
|
||||||
|
charsets = new Array(arguments.length)
|
||||||
|
for (var i = 0; i < charsets.length; i++) {
|
||||||
|
charsets[i] = arguments[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no charsets, return all requested charsets
|
||||||
|
if (!charsets || charsets.length === 0) {
|
||||||
|
return this.negotiator.charsets()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.negotiator.charsets(charsets)[0] || false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return accepted languages or best fit based on `langs`.
|
||||||
|
*
|
||||||
|
* Given `Accept-Language: en;q=0.8, es, pt`
|
||||||
|
* an array sorted by quality is returned:
|
||||||
|
*
|
||||||
|
* ['es', 'pt', 'en']
|
||||||
|
*
|
||||||
|
* @param {String|Array} langs...
|
||||||
|
* @return {Array|String}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
Accepts.prototype.lang =
|
||||||
|
Accepts.prototype.langs =
|
||||||
|
Accepts.prototype.language =
|
||||||
|
Accepts.prototype.languages = function (languages_) {
|
||||||
|
var languages = languages_
|
||||||
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (languages && !Array.isArray(languages)) {
|
||||||
|
languages = new Array(arguments.length)
|
||||||
|
for (var i = 0; i < languages.length; i++) {
|
||||||
|
languages[i] = arguments[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no languages, return all requested languages
|
||||||
|
if (!languages || languages.length === 0) {
|
||||||
|
return this.negotiator.languages()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.negotiator.languages(languages)[0] || false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert extnames to mime.
|
||||||
|
*
|
||||||
|
* @param {String} type
|
||||||
|
* @return {String}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function extToMime (type) {
|
||||||
|
return type.indexOf('/') === -1
|
||||||
|
? mime.lookup(type)
|
||||||
|
: type
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if mime is valid.
|
||||||
|
*
|
||||||
|
* @param {String} type
|
||||||
|
* @return {String}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function validMime (type) {
|
||||||
|
return typeof type === 'string'
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user