-
Notifications
You must be signed in to change notification settings - Fork 3.4k
refactor: Data context cleanup & IPC bindings for data push #18357
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
|
Thanks for taking the time to open a PR!
|
* unified-desktop-gui: chore: improving component test infra (#18378) chore(launchpad): launchpad UI tweaks (#18369) feat: wire up add project button (#18320) feat(unify): adding larger defaults for the Launchpad window (#18248) fix(app): allow launching app dev server w/o relying on `supportFile` to bundle deps (#18354) feat(unify): reporter dark theme (#18313) feat(launchpad): UNIFY-371 header menu (#18338)
|
|
||
| on('task', { | ||
| withCtx (fnString: string) { | ||
| return new Function('ctx', `return (${fnString})(ctx)`).call(undefined, ctx) |
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.
cute
| .finally(() => { | ||
| _stopServer() | ||
| windows.focusMainWindow() | ||
| require('./windows').focusMainWindow() |
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.
reminder for me to clean this up and pass this as a callback function to avoid requiring electron
|
We also need to refactor |
* unified-desktop-gui: (40 commits) feat: index.html configurability and storybook support (#18242) fix: remove .json check from require_async, prevent child_process spawn (#18416) percy snapshot the tooltip visually, prevent it from being hidden fix: failing tests from #18372 (#18414) fix: `everyNthFrame` should only be applied for Chrome 89+ (#18392) feat(app): render spec list, command log, iframe (#18372) fix: drag and drop to be correct directory (#18400) refactor: Add GitDataSource, FileDataSource, toast for errors (#18385) docs: General updates to contributing guide (#18283) Add shorter --ct alias for --component Add --e2e and --component CLI options chore: Update Chrome (beta) to 95.0.4638.40 (#18389) chore: use circleci timings split for e2e tests (#18367) fix: fixed title (#18370) chore(deps): update dependency electron to v14 🌟 (#18384) chore(server): share client route (#18215) fix: Prevent Cypress from crashing when argument parsing "spec: {}" (#18312) chore: update husky dev dependency to v7 (#18345) feat: add defineConfig function to help type config (#18302) chore: Update Chrome (stable) to 94.0.4606.71 (#18324) ...
* unified-desktop-gui: feat(app): persist current spec in data context, update runner workflow for demo (#18406)
| import type { Exchange, Operation } from '@urql/core' | ||
| import type { Socket } from '@packages/socket/lib/browser' | ||
|
|
||
| export const pubSubExchange = (io: Socket): Exchange => { |
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 where the queries are watched for refresh on push signal.
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.
Are we actually using this somewhere or not yet? It would be good to see an example of "how to push things". I'm guessing there might be one here, but there is a lot of files - might be good to include a link to the file in the PR description so everyone can easily see it.
lmiller1990
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.
Some misc comments - I couldn't immediately see an example of where we are actually pushing something from the server here? Do we have an example of "how to do it" or not yet?
| } | ||
|
|
||
| clearActiveProject () { | ||
| async clearActiveProject () { |
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.
Silly question but can this not just be
clearActiveProject () {
this.ctx.appData.activeProject = null
return this.api.closeActiveProject()
}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.
Yeah it can be, I think I might have written this way was because it was unclear what closeActiveProject is returning and didn't want to imply that you could rely on whatever the return value from that was
| } | ||
|
|
||
| export function makeUrqlClient (): Client { | ||
| export function makeUrqlClient (target: 'launchpad' | 'app'): Client { |
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 think we have these typed in resolve-dist, but probably not a big deal to duplicate them. But might be good to have a single place to define these?
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.
Maybe... for simple types like this I tend to not care about duplication too much
|
|
||
| module.exports = { | ||
| interface EventsStartArgs extends LaunchArgs { | ||
| onFocusTests: () => void |
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 think we started defining these already, full text search for export interface OpenProjectLaunchOptions, might be good to have them all in one place (ideally in @types
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 specifically extending LaunchArgs which is defined in @types with values that are local here / specific to Events.start
|
|
||
| const { getBrowsers } = browserUtils | ||
|
|
||
| interface MakeDataContextOptions { |
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.
nice, I am glad this is isn't in gui/events anymore.
| msg: nonNull(stringArg()), | ||
| }, | ||
| resolve: (root, args, ctx) => { | ||
| ctx.emitter.toLaunchpad(args.msg) |
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.
What is the purpose of having this as a mutation? Isn't the idea to be able to push things to GraphQL independantly of GraphQL (eg, via some other event/trigger)?
What is the best pattern here? Do we just grab the data context (import it however) and call emiiter.toLaunchpad, or would we be making a GraphQL mutation request to the server to access the emitter?
An example might be doing a background check to see if the git status of a file has changed via some watcher. How would we notify GraphQL that it needs to re-query to get the latest data? Woudl we make an actual request to GraphQL or just grab the context and call emitter.toApp('get:new-files') (for example)?
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 was just for testing, we can delete this
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.
An example might be doing a background check to see if the git status of a file has changed via some watcher. How would we notify GraphQL that it needs to re-query to get the latest data? Woudl we make an actual request to GraphQL or just grab the context and call emitter.toApp('get:new-files') (for example)?
Currently we just call ctx.emitter.toApp() from wherever in the background (watching, or whatever) and it'll signal the app to refetch any queries. Going for simplicitly rather than optimizing / narrowing the data fetched until it seems necessary due to perf or similar.
Summary
Adds Socket.io bindings for pushing data from the
DataContextto trigger a refresh of any queries that need updating on the client. Triggered withctx.emitter.toApp()/ctx.emitter.toLaunchpad(), will trigger a refetch of any queries currently being executed.Additionally, does a lot of work to pass the GraphQL & App server port info to the frontend clients, which enables better e2e testing of the launchpad & app. Created
DataContextShellwhich is the bare minimum API threaded through theopen_project/ServerBasewithout needing a major refactor of tests - we just auto-create theDataContextShellif one isn't passed, but we will ensure one is passed from any new codepaths. This approach will provide a starting point to extract more server logic into thedata-contextlayer.We are testing against the
dist'ed.htmlfiles, by passing the ports via the query string, otherwise the ports will be passed via injection when the HTML is rendered. This injection / testing pattern necessitates that we use hash-routing within the main app area to keep things simple.Moves the
data-contextsetup tomakeDataContext, rather than having it in thelib/gui/events, since we're going to need to create the data context in other locations as well.Upgrades
ts-nodeto give us better sourcemapping when we're debugging, and addstypescript-cached-transpileto make transpilation more consistent / possible to debug between the app & plugins (since we're now using the plugins to test the app itsself, the sourcemaps need to line up).UNIFY-413
Setting up bi-directional data communication w/ Sockets