feat: support for watching jacscript file in devtools
This commit is contained in:
Родитель
23b8fd2de5
Коммит
339a296dc3
|
@ -102,3 +102,4 @@ dist
|
||||||
|
|
||||||
# TernJS port file
|
# TernJS port file
|
||||||
.tern-port
|
.tern-port
|
||||||
|
test.js
|
|
@ -50,6 +50,10 @@ This command will work in [GitHub codespaces](https://github.com/features/codesp
|
||||||
jacdac devtools
|
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
|
## Contributing
|
||||||
|
|
||||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||||
|
|
|
@ -39,7 +39,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "^9.0.0",
|
"commander": "^9.0.0",
|
||||||
"faye-websocket": "^0.11.4",
|
"faye-websocket": "^0.11.4",
|
||||||
"jacdac-ts": "^1.27.0"
|
"jacdac-ts": "^1.27.0",
|
||||||
|
"node-watch": "^0.7.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@semantic-release/exec": "^6.0.3",
|
"@semantic-release/exec": "^6.0.3",
|
||||||
|
@ -59,8 +60,8 @@
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"rpio": "^2.4.2",
|
"rpio": "^2.4.2",
|
||||||
"spi-device": "^3.1.2",
|
|
||||||
"serialport": "^9.2.8",
|
"serialport": "^9.2.8",
|
||||||
|
"spi-device": "^3.1.2",
|
||||||
"usb": "^2.1.2"
|
"usb": "^2.1.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|
|
@ -12,6 +12,8 @@ import {
|
||||||
Flags,
|
Flags,
|
||||||
JDFrameBuffer,
|
JDFrameBuffer,
|
||||||
FRAME_PROCESS,
|
FRAME_PROCESS,
|
||||||
|
JSONTryParse,
|
||||||
|
prettySize,
|
||||||
} from "jacdac-ts"
|
} from "jacdac-ts"
|
||||||
import { enableLogging } from "./jdlogging"
|
import { enableLogging } from "./jdlogging"
|
||||||
import { createTransports, TransportsOptions } from "./transports"
|
import { createTransports, TransportsOptions } from "./transports"
|
||||||
|
@ -29,10 +31,14 @@ const log = console.log
|
||||||
const debug = console.debug
|
const debug = console.debug
|
||||||
const error = console.error
|
const error = console.error
|
||||||
|
|
||||||
function fetchProxy(): Promise<string> {
|
function fetchProxy(localhost: boolean): Promise<string> {
|
||||||
const url = "https://microsoft.github.io/jacdac-docs/devtools/proxy"
|
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) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
https
|
protocol
|
||||||
.get(url, res => {
|
.get(url, res => {
|
||||||
if (res.statusCode != 200)
|
if (res.statusCode != 200)
|
||||||
reject(
|
reject(
|
||||||
|
@ -41,7 +47,15 @@ function fetchProxy(): Promise<string> {
|
||||||
res.setEncoding("utf8")
|
res.setEncoding("utf8")
|
||||||
let body = ""
|
let body = ""
|
||||||
res.on("data", data => (body += data))
|
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)
|
res.on("error", reject)
|
||||||
})
|
})
|
||||||
.on("error", reject)
|
.on("error", reject)
|
||||||
|
@ -56,10 +70,18 @@ export async function devToolsCommand(
|
||||||
trace?: string
|
trace?: string
|
||||||
diagnostics?: boolean
|
diagnostics?: boolean
|
||||||
localhost?: boolean
|
localhost?: boolean
|
||||||
|
jacscript?: string
|
||||||
} & TransportsOptions
|
} & TransportsOptions
|
||||||
) {
|
) {
|
||||||
const { packets, internet, trace, logging, diagnostics, localhost } =
|
const {
|
||||||
options || {}
|
packets,
|
||||||
|
internet,
|
||||||
|
trace,
|
||||||
|
logging,
|
||||||
|
diagnostics,
|
||||||
|
localhost,
|
||||||
|
jacscript: jacscriptFile,
|
||||||
|
} = options || {}
|
||||||
const port = 8081
|
const port = 8081
|
||||||
const tcpPort = 8082
|
const tcpPort = 8082
|
||||||
const listenHost = internet ? undefined : "127.0.0.1"
|
const listenHost = internet ? undefined : "127.0.0.1"
|
||||||
|
@ -73,16 +95,27 @@ export async function devToolsCommand(
|
||||||
log(` raw socket: tcp://localhost:${tcpPort}`)
|
log(` raw socket: tcp://localhost:${tcpPort}`)
|
||||||
|
|
||||||
// download proxy sources
|
// download proxy sources
|
||||||
let proxyHtml = await fetchProxy()
|
const proxyHtml = await fetchProxy(localhost)
|
||||||
if (localhost)
|
|
||||||
proxyHtml = proxyHtml.replace(
|
|
||||||
/https:\/\/microsoft.github.io\/jacdac-docs\/dashboard/g,
|
|
||||||
"http://localhost:8000/dashboard"
|
|
||||||
)
|
|
||||||
|
|
||||||
// start http server
|
// start http server
|
||||||
const clients: WebSocket[] = []
|
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 server = http.createServer(function (req, res) {
|
||||||
const parsedUrl = url.parse(req.url)
|
const parsedUrl = url.parse(req.url)
|
||||||
const pathname = parsedUrl.pathname
|
const pathname = parsedUrl.pathname
|
||||||
|
@ -118,6 +151,11 @@ export async function devToolsCommand(
|
||||||
})
|
})
|
||||||
bridge.on(FRAME_PROCESS, forwardFrame)
|
bridge.on(FRAME_PROCESS, forwardFrame)
|
||||||
bus.addBridge(bridge)
|
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 processPacket = (message: Buffer | Uint8Array, sender: string) => {
|
||||||
const data = new Uint8Array(message)
|
const data = new Uint8Array(message)
|
||||||
bridge.receiveFrameOrPacket(data, sender)
|
bridge.receiveFrameOrPacket(data, sender)
|
||||||
|
@ -140,10 +178,12 @@ export async function devToolsCommand(
|
||||||
log(`client: connected (${sender}, ${clients.length} clients)`)
|
log(`client: connected (${sender}, ${clients.length} clients)`)
|
||||||
client.on("message", (event: any) => {
|
client.on("message", (event: any) => {
|
||||||
const { data } = event
|
const { data } = event
|
||||||
processPacket(data, sender)
|
if (typeof data === "string") processMessage(data, sender)
|
||||||
|
else processPacket(data, sender)
|
||||||
})
|
})
|
||||||
client.on("close", () => removeClient(client))
|
client.on("close", () => removeClient(client))
|
||||||
client.on("error", (ev: Error) => error(ev))
|
client.on("error", (ev: Error) => error(ev))
|
||||||
|
if (sendJacscript) sendJacscript()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -207,4 +247,11 @@ export async function devToolsCommand(
|
||||||
bus.connect(true)
|
bus.connect(true)
|
||||||
server.listen(port, listenHost)
|
server.listen(port, listenHost)
|
||||||
tcpServer.listen(tcpPort, 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",
|
"--localhost",
|
||||||
"use localhost:8000 instead of the internet dashboard"
|
"use localhost:8000 instead of the internet dashboard"
|
||||||
)
|
)
|
||||||
|
.option(
|
||||||
|
"-j, --jacscript <string>",
|
||||||
|
"upload and watch source of local jacscript file"
|
||||||
|
)
|
||||||
.action(devToolsCommand)
|
.action(devToolsCommand)
|
||||||
|
|
||||||
await program.parseAsync(process.argv)
|
await program.parseAsync(process.argv)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче