-
Notifications
You must be signed in to change notification settings - Fork 107
chore: initial setup with prototype #265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
eslint.config.mjs
Outdated
| document: 'readonly', | ||
| window: 'readonly', | ||
| console: 'readonly', | ||
| process: 'readonly', | ||
| chrome: 'readonly', | ||
| browser: 'readonly', | ||
| setTimeout: 'readonly', | ||
| clearTimeout: 'readonly', | ||
| setInterval: 'readonly', | ||
| clearInterval: 'readonly', | ||
| fetch: 'readonly', | ||
| URL: 'readonly', | ||
| URLSearchParams: 'readonly', | ||
| FormData: 'readonly', | ||
| Headers: 'readonly', | ||
| Request: 'readonly', | ||
| Response: 'readonly', | ||
| Blob: 'readonly', | ||
| File: 'readonly', | ||
| FileReader: 'readonly', | ||
| localStorage: 'readonly', | ||
| sessionStorage: 'readonly', | ||
| location: 'readonly', | ||
| history: 'readonly', | ||
| navigator: 'readonly', | ||
| Element: 'readonly', | ||
| HTMLElement: 'readonly', | ||
| Event: 'readonly', | ||
| CustomEvent: 'readonly', | ||
| MutationObserver: 'readonly', | ||
| IntersectionObserver: 'readonly', | ||
| ResizeObserver: 'readonly', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue(non-blocking): Can we use https://www.npmjs.com/package/globals shorthand as per eslint/eslint#16975?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, I added these:
globals: {
...globals.node,
...globals.browser,
...globals.webextensions,
},
README.md
Outdated
| app.whenReady().then(() => { | ||
| devtron.install() | ||
| // ... | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: missing a closing brace
| app.whenReady().then(() => { | |
| devtron.install() | |
| // ... | |
| } | |
| app.whenReady().then(() => { | |
| devtron.install() | |
| // ... | |
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed: c528b44
| @@ -0,0 +1,30 @@ | |||
| 'use strict'; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue(non-blocking): Not necessary for the first commit but it would be nice to have everything in TypeScript. Can we open a follow-up issue and get that done? Not sure if we need to prioritize that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plus one here, Typescript will help a lot with long-term maintainability! Agree this doesn't need to be addressed in the scope of this initial PR, but definitely is something that would be easier to tackle earlier than later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you prefer that I keep this PR as-is and handle the TypeScript migration in a follow-up PR? Or would it be better to scrap this PR and rewrite everything in TypeScript from the start? Happy to go with whichever approach the team prefers.
Edit: As discussed in the Slack Huddle on June 12, 2025, I'll address this in a follow-up PR.
package.json
Outdated
| "postcss": "^8.5.4", | ||
| "postcss-loader": "^8.1.1", | ||
| "postcss-preset-env": "^10.2.1", | ||
| "prettier-plugin-brace-style": "^0.7.3", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: is this dep being used anywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, I've removed the prettier-plugin-brace-style dep - 497b92b
package.json
Outdated
| "main": "./lib/devtron.cjs", | ||
| "module": "./lib/devtron.mjs", | ||
| "exports": { | ||
| ".": { | ||
| "import": "./lib/devtron.mjs", | ||
| "require": "./lib/devtron.cjs" | ||
| }, | ||
| "./monitorRenderer": { | ||
| "import": "./lib/monitorRenderer.mjs", | ||
| "require": "./lib/monitorRenderer.cjs" | ||
| }, | ||
| "./monitorMain": { | ||
| "import": "./lib/monitorMain.mjs", | ||
| "require": "./lib/monitorMain.cjs" | ||
| } | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Not super familiar with this syntax but do we still need main if we have exports defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those were indeed not needed, I removed "main" and "module" both. - 497b92b
src/react/components/DetailPanel.jsx
Outdated
| <div className="mb-3"> | ||
| <span className="text-gray-600">Method: </span> | ||
| <span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border border-yellow-400 bg-yellow-100 text-yellow-800"> | ||
| {selectedRow.direction === 'renderer-to-main' ? '↓ RTM' : '↑ MTR'}{' '} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: In the long run, we should probably find a better representation than "RTM" or "MTR" because it's not immediately clear what those terms mean at a glance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I was thinking of adding a tooltip with the full name like renderer-to-main, or maybe switching to clearer terms like send and receive.
I have added this suggestion to my to-do list for now.
Should I open an issue for it ?
|
|
||
| ipcRenderer.once = (channel, listener) => { | ||
| return originalOnce(channel, (_event, ...args) => { | ||
| track('main-to-renderer', channel, args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: I think it'd be interesting to distinguish .once vs. .on vs. .invoke calls. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I think I'll save this one for after I implement Session to track IPCs from renderer-to-main since that will likely influence how I would want to handle this.
src/react/test_data/test_data.js
Outdated
| @@ -0,0 +1,69 @@ | |||
| const events = [ | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: do you have an idea on a testing plan to maybe add unit tests using this fixture data?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't finalized a testing plan yet, but I'll likely start working on it when I switch to TypeScript. The events array is currently used as placeholder data for testing the panel UI on localhost in dev mode.
package.json
Outdated
| @@ -0,0 +1,77 @@ | |||
| { | |||
| "name": "devtron", | |||
| "version": "0.1.0", | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: The previous devtron version was at 1.4.0, let's bump this to 2.0.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was actually going to suggest we set it to 0.0.0-development like our other repos, since this package will end up using automated releases. Since the repo already has a v1.4.0 tag, I believe as long as we throw in a "BREAKING CHANGE: ..." in whatever commit triggers the new release (which will be under the new @electron/devtron package name), it should jump to v2.0.0 for us and be good from there. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thank you for the context here @dsanders11!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the version to 0.0.0-development - 497b92b
package.json
Outdated
| "build": "npm run build:node && npm run build:browser", | ||
| "dev": "webpack serve --config webpack.dev.config.js" | ||
| }, | ||
| "keywords": [], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: It might be nice to match the keywords in the original devtron package.json, perhaps maybe adding ipc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the keywords in this commit - 497b92b
package.json
Outdated
| "dev": "webpack serve --config webpack.dev.config.js" | ||
| }, | ||
| "keywords": [], | ||
| "author": "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: You can put yourself here! I've also seen "Electron Community" used, feel free to use whatever you prefer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! - 497b92b
package.json
Outdated
| "src/", | ||
| "public", | ||
| "webpack.config.js", | ||
| "package.json", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nonblocking): we should remove these source code files and folders to keep the published package size small. again, maybe something to revisit when we're thinking about publishing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it! I removed the src folder and some other unnecessary files/folders and added the ones that were relevant - 497b92b
manifest.json
Outdated
| @@ -0,0 +1,27 @@ | |||
| { | |||
| "name": "devtron", | |||
| "version": "1.0.0", | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: The previous devtron manifest.json used 1.0, let's bump to 2.0.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! - 9035436
| @@ -0,0 +1,30 @@ | |||
| 'use strict'; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plus one here, Typescript will help a lot with long-term maintainability! Agree this doesn't need to be addressed in the scope of this initial PR, but definitely is something that would be easier to tackle earlier than later
| }, | ||
| "files": [ | ||
| "index.js", | ||
| "dist/", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nonblocking): not something we need to address right now but something to consider before publishing: we should test that the output of the packing the file with npm pack is what we expect and can be used by consumers via npm install {output .tgz}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted!, I’ll keep this in mind for future testing.
I tested the npm pack output locally by installing the .tgz in a fresh project, and it worked as expected.
README.md
Outdated
| ## Building and Development | ||
| - Clone the repository to your local machine | ||
| - run `npm install` to install dependencies | ||
| - run `npm link` to link the package globally |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: I think we need a npm run build step after link?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I fixed it here: c528b44
| */ | ||
| const keepAlive = () => setInterval(chrome.runtime.getPlatformInfo, 20e3); | ||
| chrome.runtime.onStartup.addListener(keepAlive); | ||
| keepAlive(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given devtron is only intended to run in Electron, we may be able to more reliably keep alive the extension without requiring hacks. The risk is that the Chrome team eventually changes this and we can no longer rely on it.
I authored serviceWorker.startTask() which will keep the service worker alive as long as it's active. It might be good to experiment with this approach.
Not a blocker for this PR though. Might be something to explore later on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, I'll start exploring and experimenting with it then.
|
|
||
| patchIpc('on'); | ||
| patchIpc('once'); | ||
| patchIpc('handle'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good first start at intercepting IPCs for the main process, especially in getting some initial data to build out the devtron views.
One thing I'd like us to explore over the summer is a more comprehensive solution to tracking main process IPCs. In this solution, it's able to keep track of IPCs to ipcMain, but misses various other channels such as webContents.ipc, webFrameMain.ipc, and serviceWorkerMain.ipc.
Earlier in the year, I was able to refactor the IPC internals so that all IPCs sent to the main process goes through the Session (electron/electron#45452). We may be able to make some changes to the Electron codebase to better support this interception use case. This would be the best approach to capture all mentioned IPC channels.
I'm good with your current approach for now, but let's start talking about how we can plan to utilize the Session internals as a followup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into it and I can capture IPC messages going from renderer to main process using the following code.
function attachIPCInterceptors(ses, label = 'session') {
ses.on('-ipc-message', (event, channel, args) => {
console.log(`[${label}] async message`, { channel, args, event})
})
ses.on('-ipc-invoke', (event, channel, args) => {
console.log(`[${label}] invoke request`, { channel, args, event})
})
ses.on('-ipc-message-sync', (event, channel, args) => {
console.log(`[${label}] sync message`, { channel, args, event})
})
}
const ses = session.defaultSession
attachIPCInterceptors(ses, 'mainSession')For now, I’ve only tested this with the defaultSession, but for partitioned sessions, I’m thinking of passing their Session objects to this utility function to attach the same listeners.
Should I switch to using Session in this PR, or should I save that change for a separate one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I switch to using Session in this PR, or should I save that change for a separate one?
Let's save it for a future PR.
1cdc06c to
6fb9eaf
Compare
package.json
Outdated
| @@ -0,0 +1,79 @@ | |||
| { | |||
| "name": "devtron", | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "name": "devtron", | |
| "name": "@electron/devtron", |
That's the package name we'll publish it under on npm when the project is done, so let's set it to that now. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this change will require other changes (and updating the README), so I'll leave those associated changes to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
erickzhao
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes addressed LGTM
samuelmaddock
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an excellent starting point, @hitarth-gg! Excited to see your work over the course of the summer.
| webContents.getAllWebContents().forEach((wc) => { | ||
| wc.send(MSG_TYPE.RENDER_EVENT, eventData); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is my understanding of the message flow correct?
main -> renderer preload -> extension content script -> extension background worker
Sending events to all WebContents likely exposes more data than desired. In a follow up PR, we can be more precise by sending an IPC from main to the extension background worker directly.
// Get Devtron extension, ideally this is cached instead of looking it up each time
const devtronExtension = session.getAllExtensions().find(ext => ext.name === 'Devtron');
// Start or get ServiceWorkerMain instance
const serviceWorker = await session.serviceWorkers.startWorkerForScope(devtronExtension.url);
// Send IPC to background worker
serviceWorker.send(MSG_TYPE.RENDER_EVENT, data);There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is my understanding of the message flow correct?
main -> renderer preload -> extension content script -> extension background worker
Yes, that's correct. I wasn't happy with my initial implementation of this, good to know this alternative exists😀.
Initial project setup with prototype
There are several things that need refinement in this prototype.
Some things that are on my to-do list as of now are:
DetailPanelat the bottom as well, currently it bugs out when the window width is smallTo correctly see the DetailPanel on the right please dock the devtools to bottom as shown in the image below. I'll likely fix this UI issue in the next PR.

I'm open to completely reworking an approach if it needs to be reconsidered.