2021-02-19 17:57:15 +08:00
|
|
|
import WebSocket from "ws"
|
2021-02-05 18:20:42 +08:00
|
|
|
import "colors";
|
2021-02-22 19:03:34 +08:00
|
|
|
import path from "path";
|
|
|
|
import { glob } from "./util";
|
|
|
|
import { Shell } from "./shell";
|
2021-03-02 15:11:16 +08:00
|
|
|
import { ChildProcess, } from "child_process";
|
2021-02-20 17:58:09 +08:00
|
|
|
|
|
|
|
export type MSG = {
|
|
|
|
type: "D2C" | "C2D" | "C2S" | "D2S" | "S2C" | "S2D",
|
|
|
|
cmd: string,
|
|
|
|
payload: { [index: string]: string }
|
|
|
|
}
|
|
|
|
|
2021-02-05 18:20:42 +08:00
|
|
|
export async function createServer() {
|
2021-02-21 01:51:59 +08:00
|
|
|
let client: WebSocket | undefined = undefined;
|
|
|
|
let debug: WebSocket | undefined = undefined;
|
2021-02-07 16:33:31 +08:00
|
|
|
let deviceId = 0
|
2021-03-02 15:11:16 +08:00
|
|
|
let debugProcess: ChildProcess | undefined = undefined;
|
2021-02-21 01:51:59 +08:00
|
|
|
const wss = new WebSocket.Server({ port: 7777 })
|
2021-02-19 17:57:15 +08:00
|
|
|
.on("connection", (ws, request) => {
|
2021-02-20 17:58:09 +08:00
|
|
|
let thisDeviceId: string
|
2021-02-19 17:57:15 +08:00
|
|
|
console.log('Connected', request.headers.host)
|
|
|
|
if (request.headers.host?.startsWith("localhost")) {
|
2021-02-20 17:58:09 +08:00
|
|
|
thisDeviceId = `Debugger#${deviceId++}`
|
2021-02-21 01:51:59 +08:00
|
|
|
console.log(`${thisDeviceId} attached to dev kit`.green)
|
|
|
|
debug = ws;
|
2021-02-19 17:57:15 +08:00
|
|
|
} else {
|
2021-02-20 17:58:09 +08:00
|
|
|
thisDeviceId = `Client#${deviceId++}`
|
2021-02-19 17:57:15 +08:00
|
|
|
console.log(`${thisDeviceId} attached to dev kit`.green)
|
|
|
|
}
|
2021-02-20 17:58:09 +08:00
|
|
|
ws.on('message', async function (result: string) {
|
|
|
|
const resultObject = JSON.parse(result) as MSG
|
2021-02-21 01:51:59 +08:00
|
|
|
if (resultObject.type === "D2C") {
|
|
|
|
if (client === undefined) {
|
2021-02-23 11:45:03 +08:00
|
|
|
if (wss.clients.size <= 1) {
|
|
|
|
debug?.send(JSON.stringify({
|
|
|
|
type: "S2D",
|
|
|
|
cmd: "DEBUG_STOP",
|
|
|
|
payload: {
|
|
|
|
msg: "No devices connected.",
|
|
|
|
}
|
|
|
|
} as MSG));
|
|
|
|
console.log("Debugger need at least one connected device.")
|
|
|
|
} else {
|
|
|
|
wss.clients.forEach(e => {
|
|
|
|
e.send(result);
|
|
|
|
})
|
|
|
|
}
|
2021-02-21 01:51:59 +08:00
|
|
|
} else {
|
|
|
|
client.send(result);
|
|
|
|
}
|
|
|
|
} else if (resultObject.type === "C2D") {
|
|
|
|
if (resultObject.cmd === "DEBUG_STOP") {
|
|
|
|
client = undefined;
|
2021-03-02 15:11:16 +08:00
|
|
|
debugProcess?.kill(0);
|
2021-02-21 01:51:59 +08:00
|
|
|
}
|
|
|
|
if (client === undefined) {
|
|
|
|
client = ws;
|
|
|
|
} else if (client !== ws) {
|
|
|
|
console.log("Can only debugging one client at the same time.".red);
|
|
|
|
}
|
|
|
|
debug?.send(result);
|
2021-02-20 17:58:09 +08:00
|
|
|
} else if (resultObject.type === "C2S") {
|
|
|
|
switch (resultObject.cmd) {
|
2021-02-22 19:03:34 +08:00
|
|
|
case 'DEBUG':
|
|
|
|
let source = resultObject.payload.source as string;
|
2021-03-02 15:11:16 +08:00
|
|
|
if (source.endsWith(".ts")) {
|
|
|
|
source = source.replace(".ts", ".js");
|
|
|
|
} else if (!source.endsWith(".js")) {
|
|
|
|
source = source + ".js"
|
2021-02-22 19:03:34 +08:00
|
|
|
}
|
2021-03-02 15:11:16 +08:00
|
|
|
const jsFile = await glob(`**/${source}`, {
|
|
|
|
cwd: path.resolve(process.cwd(), "bundle")
|
2021-02-22 19:03:34 +08:00
|
|
|
})
|
2021-03-02 15:11:16 +08:00
|
|
|
if (!!!jsFile || jsFile.length === 0) {
|
|
|
|
console.error(`Cannot find ${source} in ${path.resolve(process.cwd(), "bundle")}`);
|
2021-02-22 19:03:34 +08:00
|
|
|
}
|
2021-03-02 15:11:16 +08:00
|
|
|
const debuggingFile = path.resolve(process.cwd(), "bundle", jsFile[0]);
|
|
|
|
debugProcess = await Shell.execProcess(
|
|
|
|
"node",
|
|
|
|
[
|
|
|
|
"--inspect-brk",
|
|
|
|
debuggingFile,
|
|
|
|
],
|
|
|
|
{
|
|
|
|
env: process.env,
|
|
|
|
consoleHandler: (log) => {
|
|
|
|
console.log(`Debugger>>>`.gray, log);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
console.log(`Debugger on ${debuggingFile}`.green);
|
|
|
|
console.log(`Please open Chrome`);
|
2021-02-22 19:03:34 +08:00
|
|
|
break;
|
2021-02-20 17:58:09 +08:00
|
|
|
case 'EXCEPTION':
|
|
|
|
console.log(resultObject.payload.source.red);
|
|
|
|
console.log(resultObject.payload.exception.red);
|
|
|
|
break;
|
|
|
|
case 'LOG':
|
|
|
|
const date = new Date
|
|
|
|
const format = function (num: number) {
|
|
|
|
return (Array(2).join("0") + num).slice(-2);
|
|
|
|
};
|
|
|
|
const timeStr = `${format(date.getHours())}:${format(date.getMinutes())}:${format(date.getSeconds())}.${(Array(3).join("0") + date.getMilliseconds()).slice(-3)}`
|
|
|
|
const logContent = resultObject.payload.message
|
|
|
|
if (resultObject.payload.type === 'DEFAULT') {
|
|
|
|
console.log(`${timeStr} ${thisDeviceId} ${"[I]".green} ${logContent.green}`.bgBlue);
|
|
|
|
} else if (resultObject.payload.type === 'ERROR') {
|
|
|
|
console.log(`${timeStr} ${thisDeviceId} ${"[E]".green} ${logContent.green}`.bgRed);
|
|
|
|
} else if (resultObject.payload.type === 'WARN') {
|
|
|
|
console.log(`${timeStr.black} ${thisDeviceId.black} ${"[W]".green} ${logContent.green}`.bgYellow);
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
2021-02-19 17:57:15 +08:00
|
|
|
}
|
2021-02-21 01:51:59 +08:00
|
|
|
});
|
2021-02-19 17:57:15 +08:00
|
|
|
ws.on('close', function (code: number) {
|
2021-02-21 01:51:59 +08:00
|
|
|
console.log('close: code = ' + code, thisDeviceId);
|
|
|
|
if (ws === debug) {
|
|
|
|
console.log("quit debugging");
|
|
|
|
client?.send(JSON.stringify({
|
|
|
|
type: "S2C",
|
|
|
|
cmd: "DEBUG_STOP"
|
|
|
|
} as MSG));
|
2021-02-23 16:25:21 +08:00
|
|
|
client = undefined;
|
2021-02-21 01:51:59 +08:00
|
|
|
}
|
|
|
|
if (ws === client) {
|
|
|
|
console.log("quit debugging");
|
|
|
|
client = undefined
|
2021-02-23 11:05:14 +08:00
|
|
|
debug?.send(JSON.stringify({
|
|
|
|
type: "S2D",
|
|
|
|
cmd: "DEBUG_STOP"
|
|
|
|
} as MSG));
|
2021-02-21 01:51:59 +08:00
|
|
|
}
|
|
|
|
});
|
2021-02-19 17:57:15 +08:00
|
|
|
ws.on('error', function (code: number) {
|
|
|
|
console.log('error', code)
|
2021-02-21 01:51:59 +08:00
|
|
|
if (ws === debug) {
|
|
|
|
console.log("quit debugging");
|
|
|
|
client?.send(JSON.stringify({
|
|
|
|
type: "S2C",
|
2021-02-23 11:45:03 +08:00
|
|
|
cmd: "DEBUG_STOP",
|
|
|
|
payload: {
|
|
|
|
msg: "Debugger quit",
|
|
|
|
}
|
2021-02-21 01:51:59 +08:00
|
|
|
} as MSG));
|
|
|
|
}
|
|
|
|
if (ws === client) {
|
|
|
|
console.log("quit debugging");
|
2021-02-23 11:05:14 +08:00
|
|
|
client = undefined;
|
|
|
|
debug?.send(JSON.stringify({
|
|
|
|
type: "S2D",
|
2021-02-23 11:45:03 +08:00
|
|
|
cmd: "DEBUG_STOP",
|
|
|
|
payload: {
|
|
|
|
msg: "Debugging device quit",
|
|
|
|
}
|
2021-02-23 11:05:14 +08:00
|
|
|
} as MSG));
|
2021-02-21 01:51:59 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return wss;
|
2021-02-05 18:20:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|