diff --git a/doric-cli/assets/_launch.json b/doric-cli/assets/_launch.json index 218cdf89..1f8ce169 100644 --- a/doric-cli/assets/_launch.json +++ b/doric-cli/assets/_launch.json @@ -4,7 +4,7 @@ { "type": "node", "request": "launch", - "name": "Debug TS", + "name": "Doric Debugger", "program": "${workspaceFolder}/${relativeFile}", "preLaunchTask": "Doric Build", "sourceMaps": true, diff --git a/doric-cli/package.json b/doric-cli/package.json index bebf7717..0f267e98 100644 --- a/doric-cli/package.json +++ b/doric-cli/package.json @@ -32,14 +32,17 @@ "commander": "^6.0.0", "glob": "^7.1.6", "keypress": "^0.2.1", - "nodejs-websocket": "^1.7.2", "qrcode-terminal": "^0.12.0", "rollup": "^2.23.0", "shelljs": "^0.8.4", "source-map-merger": "^0.2.0", - "typescript": "^3.9.7" + "typescript": "^3.9.7", + "ws": "^7.4.3" }, "publishConfig": { "registry": "https://registry.npmjs.org" + }, + "devDependencies": { + "@types/ws": "^7.4.0" } } diff --git a/doric-cli/src/dev.ts b/doric-cli/src/dev.ts index 371db129..4a7740f3 100644 --- a/doric-cli/src/dev.ts +++ b/doric-cli/src/dev.ts @@ -59,7 +59,6 @@ export default async function dev() { process.stdin.resume(); await delay(3000); console.warn("Start watching"); - server.listen(7777); const cachedContents: Record = {} chokidar .watch(process.cwd() + "/bundle", { @@ -87,8 +86,8 @@ export default async function dev() { if (fs.existsSync(sourceMap)) { mergeMap(sourceMap); } - server.connections.forEach((e: any) => { - e.sendText( + server.clients.forEach((e) => { + e.send( JSON.stringify({ cmd: "RELOAD", script: content, diff --git a/doric-cli/src/server.ts b/doric-cli/src/server.ts index 1e9cdee0..61c12c88 100644 --- a/doric-cli/src/server.ts +++ b/doric-cli/src/server.ts @@ -1,95 +1,93 @@ import fs from "fs"; -import { exec, spawn } from "child_process"; -import ws from "nodejs-websocket"; +import WebSocket from "ws" import "colors"; import path from "path"; import { delay, glob } from "./util"; import { Shell } from "./shell"; export async function createServer() { - console.log("Create Server") let contextId: string = "0" - let clientConnection: any = null - let debuggerConnection: any = null + let clientConnection: WebSocket | undefined = undefined + let debuggerConnection: WebSocket | undefined = undefined let deviceId = 0 - const server = (ws as any).createServer((connection: any) => { - let thisDeviceId = deviceId++ - console.log('Connected', connection.headers.host) - if (connection.headers.host.startsWith("localhost")) { - console.log(`Debugger ${thisDeviceId} attached to dev kit`.green) - debuggerConnection = connection - clientConnection.sendText(JSON.stringify({ - cmd: 'SWITCH_TO_DEBUG', - contextId: contextId - }), () => { }) - } else { - console.log(`Client ${thisDeviceId} attached to dev kit`.green) - } - connection.on('text', async function (result: string) { - let resultObject = JSON.parse(result) - switch (resultObject.cmd) { - case 'DEBUG': - clientConnection = connection; - (server as any).debugging = true; - console.log("Enter debugging"); - contextId = resultObject.data.contextId; - const projectHome = '.'; - await fs.promises.writeFile(path.resolve(projectHome, "build", "context"), contextId, "utf-8"); - let source = resultObject.data.source as string; - if (source.startsWith(".js")) { - source = source.replace(".js", ".ts"); - } else if (!source.startsWith(".ts")) { - source = source + ".ts" - } - let sourceFile = path.resolve(projectHome, "src", source); - if (!fs.existsSync(sourceFile)) { - const tsFiles = await glob(source, { - cwd: path.resolve(projectHome, "src") - }) - if (!!!tsFiles || tsFiles.length === 0) { - console.error(`Cannot find ${source} in ${path.resolve(projectHome)}`); - } - sourceFile = tsFiles[0]; - } - console.log(connection.key + " request debug, project home: " + projectHome); - await Shell.exec("code", [projectHome, sourceFile]); - await delay(1500); - break; - case 'EXCEPTION': - console.log(resultObject.data.source.red); - console.log(resultObject.data.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)}` - let logContent = resultObject.data.message as string - - if (resultObject.data.type == 'DEFAULT') { - console.log(`${timeStr} Device ${thisDeviceId} ${"[I]".green} ${logContent.green}`.bgBlue); - } else if (resultObject.data.type == 'ERROR') { - console.log(`${timeStr} Device ${thisDeviceId} ${"[E]".green} ${logContent.green}`.bgRed); - } else if (resultObject.data.type == 'WARN') { - console.log(`${timeStr.black} ${("Device " + thisDeviceId).black} ${"[W]".green} ${logContent.green}`.bgYellow); - } - break + return new WebSocket.Server({ port: 7777 }) + .on("connection", (ws, request) => { + let thisDeviceId = `Client#${deviceId++}` + console.log('Connected', request.headers.host) + if (request.headers.host?.startsWith("localhost")) { + console.log(`Debugger ${thisDeviceId} attached to dev kit`.green) + debuggerConnection = ws + clientConnection?.send(JSON.stringify({ + cmd: 'SWITCH_TO_DEBUG', + contextId: contextId + })) + } else { + console.log(`${thisDeviceId} attached to dev kit`.green) } + ws.on('text', async function (result: string) { + let resultObject = JSON.parse(result) + switch (resultObject.cmd) { + case 'DEBUG': + clientConnection = ws; + (ws as any).debugging = true; + console.log("Enter debugging"); + contextId = resultObject.data.contextId; + const projectHome = '.'; + await fs.promises.writeFile(path.resolve(projectHome, "build", "context"), contextId, "utf-8"); + let source = resultObject.data.source as string; + if (source.startsWith(".js")) { + source = source.replace(".js", ".ts"); + } else if (!source.startsWith(".ts")) { + source = source + ".ts" + } + let sourceFile = path.resolve(projectHome, "src", source); + if (!fs.existsSync(sourceFile)) { + const tsFiles = await glob(source, { + cwd: path.resolve(projectHome, "src") + }) + if (!!!tsFiles || tsFiles.length === 0) { + console.error(`Cannot find ${source} in ${path.resolve(projectHome)}`); + } + sourceFile = tsFiles[0]; + } + console.log(thisDeviceId + " request debug, project home: " + projectHome); + await Shell.exec("code", [projectHome, sourceFile]); + await delay(1500); + break; + case 'EXCEPTION': + console.log(resultObject.data.source.red); + console.log(resultObject.data.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)}` + let logContent = resultObject.data.message as string + + if (resultObject.data.type == 'DEFAULT') { + console.log(`${timeStr} ${thisDeviceId} ${"[I]".green} ${logContent.green}`.bgBlue); + } else if (resultObject.data.type == 'ERROR') { + console.log(`${timeStr} ${thisDeviceId} ${"[E]".green} ${logContent.green}`.bgRed); + } else if (resultObject.data.type == 'WARN') { + console.log(`${timeStr.black} ${thisDeviceId.black} ${"[W]".green} ${logContent.green}`.bgYellow); + } + break + } + }) + ws.on('connect', function (code: number) { + console.log('connect', code) + }) + ws.on('close', function (code: number) { + console.log('close: code = ' + code, thisDeviceId) + console.log("quit debugging"); + (ws as any).debugging = false + }) + ws.on('error', function (code: number) { + console.log('error', code) + }) }) - connection.on('connect', function (code: number) { - console.log('connect', code) - }) - connection.on('close', function (code: number) { - console.log('close: code = ' + code, connection.key) - console.log("quit debugging"); - (server as any).debugging = false - }) - connection.on('error', function (code: number) { - console.log('error', code) - }) - }) - return server }