feat: support for watching jacscript file in devtools

This commit is contained in:
Peli de Halleux 2022-11-08 00:15:31 +00:00
Родитель 23b8fd2de5
Коммит 339a296dc3
5 изменённых файлов: 72 добавлений и 15 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -102,3 +102,4 @@ dist
# TernJS port file
.tern-port
test.js

Просмотреть файл

@ -50,6 +50,10 @@ This command will work in [GitHub codespaces](https://github.com/features/codesp
jacdac devtools
```
#### `jacscript devtools --jacscript <file>`
Starts the devtools web site and also watches/uploads the source of a given jacscript to the development web site. The dev web site will automatically compile and potentially deploy the jacscript program to a connected device.
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a

Просмотреть файл

@ -39,7 +39,8 @@
"dependencies": {
"commander": "^9.0.0",
"faye-websocket": "^0.11.4",
"jacdac-ts": "^1.27.0"
"jacdac-ts": "^1.27.0",
"node-watch": "^0.7.3"
},
"devDependencies": {
"@semantic-release/exec": "^6.0.3",
@ -59,8 +60,8 @@
},
"optionalDependencies": {
"rpio": "^2.4.2",
"spi-device": "^3.1.2",
"serialport": "^9.2.8",
"spi-device": "^3.1.2",
"usb": "^2.1.2"
},
"files": [

Просмотреть файл

@ -12,6 +12,8 @@ import {
Flags,
JDFrameBuffer,
FRAME_PROCESS,
JSONTryParse,
prettySize,
} from "jacdac-ts"
import { enableLogging } from "./jdlogging"
import { createTransports, TransportsOptions } from "./transports"
@ -29,10 +31,14 @@ const log = console.log
const debug = console.debug
const error = console.error
function fetchProxy(): Promise<string> {
const url = "https://microsoft.github.io/jacdac-docs/devtools/proxy"
function fetchProxy(localhost: boolean): Promise<string> {
const protocol = localhost ? http : https
const url = localhost
? "http://localhost:8000/devtools/proxy.html"
: "https://microsoft.github.io/jacdac-docs/devtools/proxy"
console.debug(`fetch devtools proxy at ${url}`)
return new Promise<string>((resolve, reject) => {
https
protocol
.get(url, res => {
if (res.statusCode != 200)
reject(
@ -41,7 +47,15 @@ function fetchProxy(): Promise<string> {
res.setEncoding("utf8")
let body = ""
res.on("data", data => (body += data))
res.on("end", () => resolve(body))
res.on("end", () => {
if (localhost) {
body = body.replace(
/https:\/\/microsoft.github.io\/jacdac-docs\/dashboard/g,
"http://localhost:8000/dashboard"
)
}
resolve(body)
})
res.on("error", reject)
})
.on("error", reject)
@ -56,10 +70,18 @@ export async function devToolsCommand(
trace?: string
diagnostics?: boolean
localhost?: boolean
jacscript?: string
} & TransportsOptions
) {
const { packets, internet, trace, logging, diagnostics, localhost } =
options || {}
const {
packets,
internet,
trace,
logging,
diagnostics,
localhost,
jacscript: jacscriptFile,
} = options || {}
const port = 8081
const tcpPort = 8082
const listenHost = internet ? undefined : "127.0.0.1"
@ -73,16 +95,27 @@ export async function devToolsCommand(
log(` raw socket: tcp://localhost:${tcpPort}`)
// download proxy sources
let proxyHtml = await fetchProxy()
if (localhost)
proxyHtml = proxyHtml.replace(
/https:\/\/microsoft.github.io\/jacdac-docs\/dashboard/g,
"http://localhost:8000/dashboard"
)
const proxyHtml = await fetchProxy(localhost)
// start http server
const clients: WebSocket[] = []
// upload jacscript file is needed
const sendJacscript = jacscriptFile
? () => {
const source = fs.readFileSync(jacscriptFile, {
encoding: "utf-8",
})
console.debug(`refresh jacscript (${prettySize(source.length)})`)
const msg = JSON.stringify({
type: "source",
channel: "jacscript",
source,
})
clients.forEach(c => c.send(msg))
}
: undefined
const server = http.createServer(function (req, res) {
const parsedUrl = url.parse(req.url)
const pathname = parsedUrl.pathname
@ -118,6 +151,11 @@ export async function devToolsCommand(
})
bridge.on(FRAME_PROCESS, forwardFrame)
bus.addBridge(bridge)
const processMessage = (message: string, sender: string) => {
const msg = JSONTryParse(message)
if (!msg) return
console.debug(msg)
}
const processPacket = (message: Buffer | Uint8Array, sender: string) => {
const data = new Uint8Array(message)
bridge.receiveFrameOrPacket(data, sender)
@ -140,10 +178,12 @@ export async function devToolsCommand(
log(`client: connected (${sender}, ${clients.length} clients)`)
client.on("message", (event: any) => {
const { data } = event
processPacket(data, sender)
if (typeof data === "string") processMessage(data, sender)
else processPacket(data, sender)
})
client.on("close", () => removeClient(client))
client.on("error", (ev: Error) => error(ev))
if (sendJacscript) sendJacscript()
}
})
@ -207,4 +247,11 @@ export async function devToolsCommand(
bus.connect(true)
server.listen(port, listenHost)
tcpServer.listen(tcpPort, listenHost)
if (sendJacscript) {
console.debug(`watch ${jacscriptFile}`)
fs.watch(jacscriptFile, async (eventType, filename) => {
sendJacscript()
})
}
}

Просмотреть файл

@ -58,6 +58,10 @@ async function mainCli() {
"--localhost",
"use localhost:8000 instead of the internet dashboard"
)
.option(
"-j, --jacscript <string>",
"upload and watch source of local jacscript file"
)
.action(devToolsCommand)
await program.parseAsync(process.argv)