This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Doric/doric-cli/src/server.ts

179 lines
8.4 KiB
TypeScript
Raw Normal View History

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";
import fs from "fs";
2021-02-20 17:58:09 +08:00
export type MSG = {
type: "D2C" | "C2D" | "C2S" | "D2S" | "S2C" | "S2D",
cmd: string,
payload: { [index: string]: string }
}
2023-08-11 14:00:06 +08:00
export async function createServer(port: number) {
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;
2023-08-11 14:00:06 +08:00
const wss = new WebSocket.Server({ port })
2021-02-19 17:57:15 +08:00
.on("connection", (ws, request) => {
2021-02-20 17:58:09 +08:00
let thisDeviceId: string
2023-08-11 16:24:10 +08:00
if (request.headers["role"] === "PROXY") {
thisDeviceId = `Client#${deviceId++}`
console.log(`PROXY ${thisDeviceId} attached to dev kit`.green)
} else if (request.headers["role"] === "DEBUGGER" || 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) {
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;
debugProcess?.kill("SIGABRT");
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
})
let debuggingFile: string
2021-03-02 15:11:16 +08:00
if (!!!jsFile || jsFile.length === 0) {
console.error(`Cannot find ${source} in ${path.resolve(process.cwd(), "bundle")}`);
let script = resultObject.payload.script as string;
const debuggingDir = path.resolve(process.cwd(), "debug");
if (!fs.existsSync(debuggingDir)) {
await fs.promises.mkdir(debuggingDir);
}
debuggingFile = path.resolve(debuggingDir, source);
await fs.promises.writeFile(debuggingFile, script, "utf-8");
} else {
debuggingFile = path.resolve(process.cwd(), "bundle", jsFile[0]);
2021-02-22 19:03:34 +08:00
}
2021-03-02 15:11:16 +08:00
debugProcess = await Shell.execProcess(
"node",
[
"--inspect-brk",
debuggingFile,
],
{
env: process.env,
consoleHandler: (log) => {
console.log(`Debugger>>>`.gray, log);
}
}
)
console.log(`Debugger on ${debuggingFile}`.green);
2021-03-02 17:28:20 +08:00
console.log(`Please open Chrome inspector`, "chrome://inspect/#devices".white.bgGreen);
console.log(`And click ${"Open dedicated DevTools for Node".white.bgBlue}`)
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));
client = undefined;
2021-02-21 01:51:59 +08:00
}
if (ws === client) {
console.log("quit debugging");
client = undefined
debug?.send(JSON.stringify({
type: "S2D",
cmd: "DEBUG_STOP"
} as MSG));
debugProcess?.kill("SIGABRT");
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",
cmd: "DEBUG_STOP",
payload: {
msg: "Debugger quit",
}
2021-02-21 01:51:59 +08:00
} as MSG));
}
if (ws === client) {
console.log("quit debugging");
client = undefined;
debug?.send(JSON.stringify({
type: "S2D",
cmd: "DEBUG_STOP",
payload: {
msg: "Debugging device quit",
}
} as MSG));
2021-02-21 01:51:59 +08:00
}
});
});
return wss;
2021-02-05 18:20:42 +08:00
}