From cbd7d5863e3e2e0ef04c677fa85bd7e44e8a272a Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Wed, 31 Jan 2024 12:04:19 +0100 Subject: [PATCH 01/14] Squash error from ws --- index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.html b/index.html index 7bb2393..5776ef7 100644 --- a/index.html +++ b/index.html @@ -272,6 +272,9 @@
+ From 7dee63edba7cf254727be079cb8478cd6736be0c Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Wed, 31 Jan 2024 12:04:32 +0100 Subject: [PATCH 02/14] Indentation --- lib/devtools.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/devtools.js b/lib/devtools.js index d6b8df0..d5413fa 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -54,7 +54,7 @@ customElements.define('developer-tooling', class extends HTMLElement { } h2 { margin: 0 } - p { + p { margin-block-start: 0.75em; margin-block-end: 0.75em; } @@ -95,14 +95,13 @@ customElements.define('developer-tooling', class extends HTMLElement {

Remotely inspect Pear applications.

-

Some application setup is required to enable remote debugging

Install the pear-inspect module into the application

npm install pear-inspect

Add the following code to the application, before any other code:

-
if (Pear.config.dev) {
-  const { Inspector } = await import('pear-inspect')
+
if (Pear.config.dev) {
+  const { Inspector } = await import('@holepunchto/pear-inspect')
   const inpector = await new Inspector()
   const key = await inpector.enable()
   console.log('Pear Inspector key:', key.toString('hex'))
@@ -110,7 +109,7 @@ customElements.define('developer-tooling', class extends HTMLElement {
 
               

When the application is opened in development mode the inspection key will be logged.

Paste the logged key into the input and use a compatible inspect protocol tool, such as chrome://inspect to view the remote target

-
+
From 7d6d22c1130fe519c6f246530fc4b37203a9a50b Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Wed, 31 Jan 2024 13:58:13 +0100 Subject: [PATCH 03/14] Add support loading app from pear://runtime/devtools/INSPECTOR_KEY --- lib/devtools.js | 71 ++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/lib/devtools.js b/lib/devtools.js index d5413fa..4262522 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -101,10 +101,10 @@ customElements.define('developer-tooling', class extends HTMLElement {

Add the following code to the application, before any other code:

if (Pear.config.dev) {
-  const { Inspector } = await import('@holepunchto/pear-inspect')
+  const { Inspector } = await import('pear-inspect')
   const inpector = await new Inspector()
   const key = await inpector.enable()
-  console.log('Pear Inspector key:', key.toString('hex'))
+  console.log('Debug with', key.toString('hex'))
 }

When the application is opened in development mode the inspection key will be logged.

@@ -141,36 +141,15 @@ customElements.define('developer-tooling', class extends HTMLElement { this.addKeyFormElem.addEventListener('submit', e => { e.preventDefault() const inspectorKey = this.addKeyInputElem.value - if (inspectorKey.length !== 64) { - this.addKeyErrorElem.textContent = 'Key needs to be 64 characters long' - return - } - - const sessionId = generateUuid() - const inspectorSession = new Session({ inspectorKey: b4a.from(inspectorKey, 'hex') }) - const app = { - inspectorKey, - title: '', - url: '', - inspectorSession - } - - inspectorSession.on('close', () => { - this.apps.delete(sessionId) - this.renderApps() - }) - inspectorSession.on('info', ({ filename }) => { - app.url = filename - app.title = filename.split('/').pop() - this.apps.set(sessionId, app) - this.renderApps() - }) - - this.addKeyInputElem.value = '' - this.addKeyErrorElem.textContent = '' - this.renderApps() + this.addApp(inspectorKey) }) + const shouldLoadApp = Pear.config.linkData?.startsWith('devtools/') + if (shouldLoadApp) { + const id = Pear.config.linkData.split('/').pop() + this.addApp(id) + } + const devtoolsHttpServer = http.createServer() const devToolsWsServer = new WebSocketServer({ noServer: true }) @@ -244,6 +223,7 @@ customElements.define('developer-tooling', class extends HTMLElement { div.innerHTML = `
+
devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:9229/${sessionId}
${app.title} (${app.url})
` @@ -260,7 +240,38 @@ customElements.define('developer-tooling', class extends HTMLElement { } else { this.noAppsElem.classList.remove('hidden') } + } + addApp (inspectorKey) { + const isIncorrectLength = inspectorKey.length !== 64 + if (isIncorrectLength) { + this.addKeyErrorElem.textContent = 'Key needs to be 64 characters long' + return + } + + const sessionId = generateUuid() + const inspectorSession = new Session({ inspectorKey: b4a.from(inspectorKey, 'hex') }) + const app = { + inspectorKey, + title: '', + url: '', + inspectorSession + } + + inspectorSession.on('close', () => { + this.apps.delete(sessionId) + this.renderApps() + }) + inspectorSession.on('info', ({ filename }) => { + app.url = filename + app.title = filename.split('/').pop() + this.apps.set(sessionId, app) + this.renderApps() + }) + + this.addKeyInputElem.value = '' + this.addKeyErrorElem.textContent = '' + this.renderApps() } load () { From dbc051afca4c76972ad865a1790fdee3c8b6664b Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Wed, 31 Jan 2024 15:47:05 +0100 Subject: [PATCH 04/14] Update pear-inspect --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a53994..736deb3 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,9 @@ } }, "dependencies": { - "@holepunchto/pear-inspect": "^3.0.1", "b4a": "^1.6.4", "bare-path": "^2.1.0", + "pear-inspect": "^1.0.3", "redhat-overpass-font": "^1.0.0", "ws": "^8.16.0" } From 658f260721cdfb9fbb4468f6a0fe596726aaacf4 Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Wed, 31 Jan 2024 16:03:52 +0100 Subject: [PATCH 05/14] Refactor to create server in its own method --- lib/devtools.js | 139 +++++++++++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 67 deletions(-) diff --git a/lib/devtools.js b/lib/devtools.js index 4262522..0ddf660 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -1,11 +1,12 @@ /* eslint-env browser */ import http from 'http' import { WebSocketServer } from 'ws' -import { Session } from '@holepunchto/pear-inspect' +import { Session } from 'pear-inspect' import b4a from 'b4a' customElements.define('developer-tooling', class extends HTMLElement { router = null + port = 9229 constructor () { super() @@ -150,71 +151,7 @@ customElements.define('developer-tooling', class extends HTMLElement { this.addApp(id) } - const devtoolsHttpServer = http.createServer() - const devToolsWsServer = new WebSocketServer({ noServer: true }) - - devtoolsHttpServer.listen(9229, () => console.log('[devtoolsHttpServer] running on port 9229')) - devtoolsHttpServer.on('request', (req, res) => { - if (req.url !== '/json/list') { - res.writeHead(404) - res.end() - return - } - - const targets = [...this.apps].map(([sessionId, app]) => ({ - description: 'node.js instance', // `Pear app: ${app.name}`, - devtoolsFrontendUrl: `devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:9229/${sessionId}`, - devtoolsFrontendUrlCompat: `devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9229/${sessionId}`, - faviconUrl: 'https://nodejs.org/static/images/favicons/favicon.ico', - id: sessionId, - title: app.title, - type: 'node', - url: `file://${app.url}`, - webSocketDebuggerUrl: `ws://127.0.0.1:9229/${sessionId}` - })) - - res.writeHead(200, { - 'Content-Type': 'application/json; charset=UTF-8', - 'Cache-Control': 'no-cache', - 'Content-Length': JSON.stringify(targets).length - }) - res.end(JSON.stringify(targets)) - }) - devtoolsHttpServer.on('upgrade', (request, socket, head) => { - console.log(`[devtoolsHttpServer] UPGRADE. url=${request.url}`) - const sessionId = request.url.substr(1) - const sessionIdExists = this.apps.has(sessionId) - if (!sessionIdExists) return socket.destroy() - - devToolsWsServer.handleUpgrade(request, socket, head, ws => devToolsWsServer.emit('connection', ws, request)) - }) - - devToolsWsServer.on('connection', (devtoolsSocket, request) => { - const sessionId = request.url.substr(1) - const app = this.apps.get(sessionId) - if (!app) return devtoolsSocket.destroy() - - const { inspectorSession } = app - - const onMessage = msg => { - const { pearInspectMethod } = msg - const isACDPMessage = !pearInspectMethod - - if (isACDPMessage) return devtoolsSocket.send(JSON.stringify(msg)) - } - inspectorSession.connect() - inspectorSession.on('message', onMessage) - devtoolsSocket.on('message', msg => inspectorSession.post(JSON.parse(msg))) - devtoolsSocket.on('close', () => { - inspectorSession.disconnect() - inspectorSession.off('message', onMessage) - app.connected = false - this.renderApps() - }) - - app.connected = true - this.renderApps() - }) + this.initServer() } renderApps () { @@ -223,7 +160,7 @@ customElements.define('developer-tooling', class extends HTMLElement { div.innerHTML = `
-
devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:9229/${sessionId}
+
devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:${this.port}/${sessionId}
${app.title} (${app.url})
` @@ -274,6 +211,74 @@ customElements.define('developer-tooling', class extends HTMLElement { this.renderApps() } + initServer () { + const devtoolsHttpServer = http.createServer() + const devToolsWsServer = new WebSocketServer({ noServer: true }) + + devtoolsHttpServer.listen(this.port, () => console.log(`[devtoolsHttpServer] running on port ${this.port}`)) + devtoolsHttpServer.on('request', (req, res) => { + if (req.url !== '/json/list') { + res.writeHead(404) + res.end() + return + } + + const targets = [...this.apps].map(([sessionId, app]) => ({ + description: 'node.js instance', // `Pear app: ${app.name}`, + devtoolsFrontendUrl: `devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:${this.port}/${sessionId}`, + devtoolsFrontendUrlCompat: `devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:${this.port}/${sessionId}`, + faviconUrl: 'https://nodejs.org/static/images/favicons/favicon.ico', + id: sessionId, + title: app.title, + type: 'node', + url: `file://${app.url}`, + webSocketDebuggerUrl: `ws://127.0.0.1:${this.port}/${sessionId}` + })) + + res.writeHead(200, { + 'Content-Type': 'application/json; charset=UTF-8', + 'Cache-Control': 'no-cache', + 'Content-Length': JSON.stringify(targets).length + }) + res.end(JSON.stringify(targets)) + }) + devtoolsHttpServer.on('upgrade', (request, socket, head) => { + console.log(`[devtoolsHttpServer] UPGRADE. url=${request.url}`) + const sessionId = request.url.substr(1) + const sessionIdExists = this.apps.has(sessionId) + if (!sessionIdExists) return socket.destroy() + + devToolsWsServer.handleUpgrade(request, socket, head, ws => devToolsWsServer.emit('connection', ws, request)) + }) + + devToolsWsServer.on('connection', (devtoolsSocket, request) => { + const sessionId = request.url.substr(1) + const app = this.apps.get(sessionId) + if (!app) return devtoolsSocket.destroy() + + const { inspectorSession } = app + + const onMessage = msg => { + const { pearInspectMethod } = msg + const isACDPMessage = !pearInspectMethod + + if (isACDPMessage) return devtoolsSocket.send(JSON.stringify(msg)) + } + inspectorSession.connect() + inspectorSession.on('message', onMessage) + devtoolsSocket.on('message', msg => inspectorSession.post(JSON.parse(msg))) + devtoolsSocket.on('close', () => { + inspectorSession.disconnect() + inspectorSession.off('message', onMessage) + app.connected = false + this.renderApps() + }) + + app.connected = true + this.renderApps() + }) + } + load () { this.style.display = '' } From a0d53d90240b555aacf23b06adc7d6e39aa9ae61 Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Wed, 31 Jan 2024 16:12:29 +0100 Subject: [PATCH 06/14] Remove debugging line --- lib/devtools.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/devtools.js b/lib/devtools.js index 0ddf660..033db31 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -160,7 +160,6 @@ customElements.define('developer-tooling', class extends HTMLElement { div.innerHTML = `
-
devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:${this.port}/${sessionId}
${app.title} (${app.url})
` From b386acce19c18749873a6d0ac61c602773c5fe26 Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Thu, 1 Feb 2024 13:17:20 +0100 Subject: [PATCH 07/14] Add buttons to Copy URL, and open in Chrome --- lib/devtools.js | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/devtools.js b/lib/devtools.js index 033db31..f4b50e4 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -3,6 +3,7 @@ import http from 'http' import { WebSocketServer } from 'ws' import { Session } from 'pear-inspect' import b4a from 'b4a' +import { spawn } from 'child_process' customElements.define('developer-tooling', class extends HTMLElement { router = null @@ -29,20 +30,34 @@ customElements.define('developer-tooling', class extends HTMLElement { .app { display: flex; align-items: center; + padding: 0.25rem; + padding-top: 0.1rem; + padding-bottom: 0.15rem; } .app .title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .app:hover .copy, + .app:hover .open-in-chrome, .app:hover .remove { display: block; } + .app .copy, + .app .open-in-chrome { + margin-right: 10px; + } + .app .copy, + .app .open-in-chrome, .app .remove { cursor: pointer; - padding-right: 10px; - margin-left: calc(-1rem - 10px); - width: 1rem; + background: #3a4816; + color: #efeaea; + padding: 0 0.25rem; + font-family: 'overpass-mono'; + border-radius: 1px; + white-space: nowrap; display: none; } #remote-inspect-explain { @@ -159,10 +174,18 @@ customElements.define('developer-tooling', class extends HTMLElement { const div = document.createElement('div') div.innerHTML = `
-
${app.title} (${app.url})
+
Copy URL
+
Open in Chrome
+
` + div.querySelector('.copy').addEventListener('click', () => { + navigator.clipboard.writeText(`devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:${this.port}/${sessionId}`) + }) + div.querySelector('.open-in-chrome').addEventListener('click', () => { + openChrome(`devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:${this.port}/${sessionId}`) + }) div.querySelector('.remove').addEventListener('click', () => { this.apps.delete(sessionId) this.renderApps() @@ -300,3 +323,16 @@ function generateUuid () { } return result } + +function openChrome (url) { + const params = { + darwin: ['open', '-a', 'Google Chrome', url], + linux: ['google-chrome', url], + win32: ['start', 'chrome', url] + }[process.platform] + + if (!params) throw new Error('Cannot open Chrome') + + const [command, ...args] = params + spawn(command, args) +} From 1be8be058fc669d2c952188614bdc9cd0ff6b781 Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Thu, 1 Feb 2024 13:37:34 +0100 Subject: [PATCH 08/14] Start on random unused port. Support links to be pasted --- lib/devtools.js | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/devtools.js b/lib/devtools.js index f4b50e4..a70fad0 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -7,7 +7,6 @@ import { spawn } from 'child_process' customElements.define('developer-tooling', class extends HTMLElement { router = null - port = 9229 constructor () { super() @@ -109,7 +108,7 @@ customElements.define('developer-tooling', class extends HTMLElement {

Developer Tooling

-
+

Remotely inspect Pear applications.

Some application setup is required to enable remote debugging

Install the pear-inspect module into the application

@@ -120,13 +119,14 @@ customElements.define('developer-tooling', class extends HTMLElement { const { Inspector } = await import('pear-inspect') const inpector = await new Inspector() const key = await inpector.enable() - console.log('Debug with', key.toString('hex')) + console.log('Debug with pear://runtime/devtools/' + + key.toString('hex')) }

When the application is opened in development mode the inspection key will be logged.

-

Paste the logged key into the input and use a compatible inspect protocol tool, such as chrome://inspect to view the remote target

+

Paste the logged key into the input to add it. Then open in Chrome or copy the URL to a compatible inspect tool to view the remote target.

-
+
@@ -138,6 +138,7 @@ customElements.define('developer-tooling', class extends HTMLElement {
+
` this.root = this.attachShadow({ mode: 'open' }) @@ -162,14 +163,13 @@ customElements.define('developer-tooling', class extends HTMLElement { const shouldLoadApp = Pear.config.linkData?.startsWith('devtools/') if (shouldLoadApp) { - const id = Pear.config.linkData.split('/').pop() - this.addApp(id) + this.addApp(Pear.config.linkData) } this.initServer() } - renderApps () { + render () { this.appsElem.replaceChildren(...[...this.apps].map(([sessionId, app]) => { const div = document.createElement('div') div.innerHTML = ` @@ -188,7 +188,7 @@ customElements.define('developer-tooling', class extends HTMLElement { }) div.querySelector('.remove').addEventListener('click', () => { this.apps.delete(sessionId) - this.renderApps() + this.render() }) return div @@ -202,6 +202,8 @@ customElements.define('developer-tooling', class extends HTMLElement { } addApp (inspectorKey) { + const isUrl = inspectorKey.includes('devtools/') + if (isUrl) inspectorKey = inspectorKey.split('devtools/').pop() const isIncorrectLength = inspectorKey.length !== 64 if (isIncorrectLength) { this.addKeyErrorElem.textContent = 'Key needs to be 64 characters long' @@ -219,25 +221,28 @@ customElements.define('developer-tooling', class extends HTMLElement { inspectorSession.on('close', () => { this.apps.delete(sessionId) - this.renderApps() + this.render() }) inspectorSession.on('info', ({ filename }) => { app.url = filename app.title = filename.split('/').pop() this.apps.set(sessionId, app) - this.renderApps() + this.render() }) this.addKeyInputElem.value = '' this.addKeyErrorElem.textContent = '' - this.renderApps() + this.render() } initServer () { const devtoolsHttpServer = http.createServer() const devToolsWsServer = new WebSocketServer({ noServer: true }) - devtoolsHttpServer.listen(this.port, () => console.log(`[devtoolsHttpServer] running on port ${this.port}`)) + devtoolsHttpServer.listen(0, () => { + this.port = devtoolsHttpServer.address().port + console.log(`[devtoolsHttpServer] running on port ${this.port}`) + }) devtoolsHttpServer.on('request', (req, res) => { if (req.url !== '/json/list') { res.writeHead(404) @@ -293,11 +298,11 @@ customElements.define('developer-tooling', class extends HTMLElement { inspectorSession.disconnect() inspectorSession.off('message', onMessage) app.connected = false - this.renderApps() + this.render() }) app.connected = true - this.renderApps() + this.render() }) } From 00dc957e0b8da080fc62b92cbceb5dae401193b7 Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Thu, 1 Feb 2024 13:48:34 +0100 Subject: [PATCH 09/14] Display port --- lib/devtools.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/devtools.js b/lib/devtools.js index a70fad0..e4f6d30 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -67,6 +67,13 @@ customElements.define('developer-tooling', class extends HTMLElement { float:right; max-width:40%; } + #server-message { + font-size: 0.8rem; + margin-top: 30px; + } + #server-message.hidden { + display: none; + } h2 { margin: 0 } p { @@ -136,6 +143,9 @@ customElements.define('developer-tooling', class extends HTMLElement {

Apps

No apps added. Add an inspect key to start debugging.

+
@@ -199,6 +209,11 @@ customElements.define('developer-tooling', class extends HTMLElement { } else { this.noAppsElem.classList.remove('hidden') } + + if (this.port) { + this.root.querySelector('#server-location').textContent = `location:${this.port}` + this.root.querySelector('#server-message').classList.remove('hidden') + } } addApp (inspectorKey) { @@ -242,6 +257,7 @@ customElements.define('developer-tooling', class extends HTMLElement { devtoolsHttpServer.listen(0, () => { this.port = devtoolsHttpServer.address().port console.log(`[devtoolsHttpServer] running on port ${this.port}`) + this.render() }) devtoolsHttpServer.on('request', (req, res) => { if (req.url !== '/json/list') { From 3e2344fddc10de0ace1eb7c8dcdf8b9cd0def57c Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Thu, 1 Feb 2024 14:06:14 +0100 Subject: [PATCH 10/14] lol fix --- lib/devtools.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/devtools.js b/lib/devtools.js index e4f6d30..07ec20f 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -211,7 +211,7 @@ customElements.define('developer-tooling', class extends HTMLElement { } if (this.port) { - this.root.querySelector('#server-location').textContent = `location:${this.port}` + this.root.querySelector('#server-location').textContent = `localhost:${this.port}` this.root.querySelector('#server-message').classList.remove('hidden') } } From bb706e06dd568bffd4505489d96a344abe9b0e7b Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Thu, 1 Feb 2024 14:50:01 +0100 Subject: [PATCH 11/14] Able to change port --- lib/devtools.js | 67 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/lib/devtools.js b/lib/devtools.js index 07ec20f..bac1536 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -7,6 +7,7 @@ import { spawn } from 'child_process' customElements.define('developer-tooling', class extends HTMLElement { router = null + port = 9229 constructor () { super() @@ -18,11 +19,12 @@ customElements.define('developer-tooling', class extends HTMLElement { width: 100%; } - #add-key-error { + #add-key-error, + #change-port-error { color: red; } - #no-apps.hidden { + .hidden { display: none; } @@ -50,6 +52,9 @@ customElements.define('developer-tooling', class extends HTMLElement { .app .copy, .app .open-in-chrome, .app .remove { + display: none; + } + .button { cursor: pointer; background: #3a4816; color: #efeaea; @@ -57,7 +62,6 @@ customElements.define('developer-tooling', class extends HTMLElement { font-family: 'overpass-mono'; border-radius: 1px; white-space: nowrap; - display: none; } #remote-inspect-explain { float:left; @@ -71,9 +75,6 @@ customElements.define('developer-tooling', class extends HTMLElement { font-size: 0.8rem; margin-top: 30px; } - #server-message.hidden { - display: none; - } h2 { margin: 0 } p { @@ -144,7 +145,19 @@ customElements.define('developer-tooling', class extends HTMLElement {

No apps added. Add an inspect key to start debugging.

@@ -157,20 +170,37 @@ customElements.define('developer-tooling', class extends HTMLElement { this.addKeyFormElem = this.root.querySelector('#add-key-form') this.addKeyInputElem = this.root.querySelector('#add-key-input') this.addKeyErrorElem = this.root.querySelector('#add-key-error') + this.changePortFormElem = this.root.querySelector('#change-port-form') + this.changePortInputElem = this.root.querySelector('#change-port-input') + this.changePortErrorElem = this.root.querySelector('#change-port-error') + this.changePortShowElem = this.root.querySelector('#change-port-show') this.appsElem = this.root.querySelector('#apps') this.noAppsElem = this.root.querySelector('#no-apps') + this.changePortElem = this.root.querySelector('#change-port') this.apps = new Map() this.addKeyInputElem.addEventListener('keypress', e => { this.addKeyErrorElem.textContent = '' }) - this.addKeyFormElem.addEventListener('submit', e => { e.preventDefault() const inspectorKey = this.addKeyInputElem.value this.addApp(inspectorKey) }) + this.changePortInputElem.addEventListener('keypress', () => { + this.changePortErrorElem.textContent = '' + }) + this.changePortShowElem.addEventListener('click', () => { + this.changePortFormElem.classList.remove('hidden') + }) + this.changePortFormElem.addEventListener('submit', e => { + e.preventDefault() + this.port = Number(this.changePortInputElem.value) + this.initServer() + }) + + const shouldLoadApp = Pear.config.linkData?.startsWith('devtools/') if (shouldLoadApp) { this.addApp(Pear.config.linkData) @@ -185,9 +215,9 @@ customElements.define('developer-tooling', class extends HTMLElement { div.innerHTML = `
${app.title} (${app.url})
-
Copy URL
-
Open in Chrome
-
+
Copy URL
+
Open in Chrome
+
` div.querySelector('.copy').addEventListener('click', () => { @@ -211,7 +241,7 @@ customElements.define('developer-tooling', class extends HTMLElement { } if (this.port) { - this.root.querySelector('#server-location').textContent = `localhost:${this.port}` + this.root.querySelector('#server-location').textContent = `http://localhost:${this.port}` this.root.querySelector('#server-message').classList.remove('hidden') } } @@ -251,15 +281,18 @@ customElements.define('developer-tooling', class extends HTMLElement { } initServer () { - const devtoolsHttpServer = http.createServer() + this.devtoolsHttpServer?.close() + + this.devtoolsHttpServer = http.createServer() const devToolsWsServer = new WebSocketServer({ noServer: true }) - devtoolsHttpServer.listen(0, () => { - this.port = devtoolsHttpServer.address().port + this.devtoolsHttpServer.listen(this.port, () => { console.log(`[devtoolsHttpServer] running on port ${this.port}`) this.render() + this.changePortFormElem.classList.add('hidden') }) - devtoolsHttpServer.on('request', (req, res) => { + this.devtoolsHttpServer.on('error', err => this.changePortErrorElem.textContent = err?.message) + this.devtoolsHttpServer.on('request', (req, res) => { if (req.url !== '/json/list') { res.writeHead(404) res.end() @@ -285,7 +318,7 @@ customElements.define('developer-tooling', class extends HTMLElement { }) res.end(JSON.stringify(targets)) }) - devtoolsHttpServer.on('upgrade', (request, socket, head) => { + this.devtoolsHttpServer.on('upgrade', (request, socket, head) => { console.log(`[devtoolsHttpServer] UPGRADE. url=${request.url}`) const sessionId = request.url.substr(1) const sessionIdExists = this.apps.has(sessionId) From 3be059eddebda09e30603e3888c7c3d040d64317 Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Thu, 1 Feb 2024 14:53:30 +0100 Subject: [PATCH 12/14] Add pressing escape hides change port form --- lib/devtools.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/devtools.js b/lib/devtools.js index bac1536..252a84f 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -179,7 +179,7 @@ customElements.define('developer-tooling', class extends HTMLElement { this.changePortElem = this.root.querySelector('#change-port') this.apps = new Map() - this.addKeyInputElem.addEventListener('keypress', e => { + this.addKeyInputElem.addEventListener('keydown', e => { this.addKeyErrorElem.textContent = '' }) this.addKeyFormElem.addEventListener('submit', e => { @@ -188,8 +188,13 @@ customElements.define('developer-tooling', class extends HTMLElement { this.addApp(inspectorKey) }) - this.changePortInputElem.addEventListener('keypress', () => { + this.changePortInputElem.addEventListener('keydown', e => { + const isEscape = e.key === 'Escape' this.changePortErrorElem.textContent = '' + if (isEscape) { + this.changePortFormElem.classList.add('hidden') + this.changePortInputElem.value = '' + } }) this.changePortShowElem.addEventListener('click', () => { this.changePortFormElem.classList.remove('hidden') From 9c6036187b0daccb83ca3a454c91cf503c2d1f3e Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Thu, 1 Feb 2024 14:56:34 +0100 Subject: [PATCH 13/14] Hide change input button until hover --- lib/devtools.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/devtools.js b/lib/devtools.js index 252a84f..58ddfd3 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -24,6 +24,13 @@ customElements.define('developer-tooling', class extends HTMLElement { color: red; } + #server-message:hover #change-port-show { + display: inline-block; + } + #change-port-show { + display: none; + } + .hidden { display: none; } From 81cda96e5c965b1af3eefd0c565839280654550e Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Thu, 1 Feb 2024 17:25:34 +0100 Subject: [PATCH 14/14] Change port --- lib/devtools.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/devtools.js b/lib/devtools.js index 58ddfd3..49f9741 100644 --- a/lib/devtools.js +++ b/lib/devtools.js @@ -7,7 +7,7 @@ import { spawn } from 'child_process' customElements.define('developer-tooling', class extends HTMLElement { router = null - port = 9229 + port = 9342 constructor () { super()