init
This commit is contained in:
commit
2bd43d8702
|
@ -0,0 +1,2 @@
|
||||||
|
.env
|
||||||
|
node_modules
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "sync",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": "^3.5.3",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"ws": "^8.14.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
chokidar:
|
||||||
|
specifier: ^3.5.3
|
||||||
|
version: 3.5.3
|
||||||
|
dotenv:
|
||||||
|
specifier: ^16.3.1
|
||||||
|
version: 16.3.1
|
||||||
|
ws:
|
||||||
|
specifier: ^8.14.2
|
||||||
|
version: 8.14.2
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
/anymatch@3.1.3:
|
||||||
|
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
dependencies:
|
||||||
|
normalize-path: 3.0.0
|
||||||
|
picomatch: 2.3.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/binary-extensions@2.2.0:
|
||||||
|
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/braces@3.0.2:
|
||||||
|
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dependencies:
|
||||||
|
fill-range: 7.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/chokidar@3.5.3:
|
||||||
|
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||||
|
engines: {node: '>= 8.10.0'}
|
||||||
|
dependencies:
|
||||||
|
anymatch: 3.1.3
|
||||||
|
braces: 3.0.2
|
||||||
|
glob-parent: 5.1.2
|
||||||
|
is-binary-path: 2.1.0
|
||||||
|
is-glob: 4.0.3
|
||||||
|
normalize-path: 3.0.0
|
||||||
|
readdirp: 3.6.0
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents: 2.3.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/dotenv@16.3.1:
|
||||||
|
resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/fill-range@7.0.1:
|
||||||
|
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dependencies:
|
||||||
|
to-regex-range: 5.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/fsevents@2.3.3:
|
||||||
|
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||||
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/glob-parent@5.1.2:
|
||||||
|
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
dependencies:
|
||||||
|
is-glob: 4.0.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/is-binary-path@2.1.0:
|
||||||
|
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dependencies:
|
||||||
|
binary-extensions: 2.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/is-extglob@2.1.1:
|
||||||
|
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/is-glob@4.0.3:
|
||||||
|
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dependencies:
|
||||||
|
is-extglob: 2.1.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/is-number@7.0.0:
|
||||||
|
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||||
|
engines: {node: '>=0.12.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/normalize-path@3.0.0:
|
||||||
|
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/picomatch@2.3.1:
|
||||||
|
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||||
|
engines: {node: '>=8.6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/readdirp@3.6.0:
|
||||||
|
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||||
|
engines: {node: '>=8.10.0'}
|
||||||
|
dependencies:
|
||||||
|
picomatch: 2.3.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/to-regex-range@5.0.1:
|
||||||
|
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||||
|
engines: {node: '>=8.0'}
|
||||||
|
dependencies:
|
||||||
|
is-number: 7.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/ws@8.14.2:
|
||||||
|
resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==}
|
||||||
|
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
|
||||||
|
dev: false
|
|
@ -0,0 +1,80 @@
|
||||||
|
const WebSocket = require("ws");
|
||||||
|
const { EventEmitter } = require("events");
|
||||||
|
|
||||||
|
class Client extends EventEmitter {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.bindEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
if (!this.started) return;
|
||||||
|
this.started = true;
|
||||||
|
|
||||||
|
this.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
this.ws = new WebSocket(process.env.SYNC_URI);
|
||||||
|
|
||||||
|
this.ws.on("open", () => {});
|
||||||
|
|
||||||
|
this.ws.addEventListener("close", (evt) => {
|
||||||
|
this.emit("disconnected");
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.connect();
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ws.addEventListener("error", (evt) => {
|
||||||
|
this.emit("wserror", evt);
|
||||||
|
this.ws.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ws.addEventListener("message", (evt) => {
|
||||||
|
try {
|
||||||
|
const str = evt.data.toString();
|
||||||
|
const msg = JSON.parse(str);
|
||||||
|
this.emit(msg.m, msg);
|
||||||
|
} catch (err) {
|
||||||
|
this.emit("parse_error", err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
this.started = false;
|
||||||
|
|
||||||
|
if (this.ws) {
|
||||||
|
this.ws.close();
|
||||||
|
delete this.ws;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
say(msg) {
|
||||||
|
try {
|
||||||
|
if (this.isConnected()) this.ws.send(JSON.stringify(msg));
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log(level, message) {
|
||||||
|
if (!this.isConnected()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isConnected() {
|
||||||
|
return this.ws.readyState == WebSocket.OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
bindEventListeners() {
|
||||||
|
this.on("log", (msg) => {
|
||||||
|
console.log(`[${msg.level}] ${msg.message}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { Client };
|
|
@ -0,0 +1,23 @@
|
||||||
|
require("dotenv").config();
|
||||||
|
|
||||||
|
let isServer;
|
||||||
|
|
||||||
|
process.argv.forEach((val, index, array) => {
|
||||||
|
if (val == "client") isServer = false;
|
||||||
|
if (val == "server") isServer = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof isServer == "undefined") {
|
||||||
|
// Incorrect arguments
|
||||||
|
console.log(`Usage: ${process.argv[0]} ${process.argv[1]} [client|server]`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isServer) {
|
||||||
|
const { Server } = require("./server");
|
||||||
|
Server.start();
|
||||||
|
} else {
|
||||||
|
const { Client } = require("./client");
|
||||||
|
const cl = new Client();
|
||||||
|
cl.connect();
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
const WebSocket = require("ws");
|
||||||
|
const { EventEmitter } = require("events");
|
||||||
|
|
||||||
|
function broadcast(msg) {
|
||||||
|
Server.wss.clients.forEach((ws) => {
|
||||||
|
ws.say(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(level, message) {
|
||||||
|
console.log(`[${level}] ${message}`);
|
||||||
|
broadcast({ m: "log", level, message });
|
||||||
|
}
|
||||||
|
|
||||||
|
class Server {
|
||||||
|
static start() {
|
||||||
|
this.wss = new WebSocket.Server({
|
||||||
|
port: process.env.PORT || 10911,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.wss.on("connection", (ws, req) => {
|
||||||
|
ws.preauth = new EventEmitter();
|
||||||
|
ws.evt = new EventEmitter();
|
||||||
|
|
||||||
|
ws.say = (msg) => {
|
||||||
|
ws.send(JSON.stringify(msg));
|
||||||
|
};
|
||||||
|
|
||||||
|
log("INFO", "Client connected at " + req.socket.remoteAddress);
|
||||||
|
|
||||||
|
ws.on("message", (data, isBinary) => {
|
||||||
|
try {
|
||||||
|
if (isBinary) return;
|
||||||
|
|
||||||
|
const str = data.toString();
|
||||||
|
const converted = JSON.parse(str);
|
||||||
|
|
||||||
|
if (converted.m) {
|
||||||
|
ws.preauth.emit(converted.m, converted);
|
||||||
|
|
||||||
|
if (ws.authed) {
|
||||||
|
ws.evt.emit(converted.m, converted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.preauth.on("hi", (msg) => {
|
||||||
|
if (!msg.project) return;
|
||||||
|
|
||||||
|
ws.authed = true;
|
||||||
|
ws.project = msg.project;
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.evt.on("log", (msg) => {
|
||||||
|
if (!msg.level) return;
|
||||||
|
if (!msg.message) return;
|
||||||
|
|
||||||
|
log(msg.level, `From ${req.socket.remoteAddress}: ${msg.message}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.evt.on("broadcast", (msg) => {
|
||||||
|
if (!msg.msg) return;
|
||||||
|
if (typeof msg.msg !== "object") return;
|
||||||
|
if (!msg.msg.m) return;
|
||||||
|
|
||||||
|
broadcast({
|
||||||
|
m: "broadcast",
|
||||||
|
msg: msg.msg,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static stop() {
|
||||||
|
this.wss.close();
|
||||||
|
delete this.wss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { Server };
|
Loading…
Reference in New Issue