-
Notifications
You must be signed in to change notification settings - Fork 75
Nadro/adhoc/system io machine #6352
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
…ts. This is bricking JS state
…lectron implemented in vitest?
…, a few missing features still
…the requestProjectName
…hard coded in poor spot for now.
…odeling-app into nadro/adhoc/system-io-machine
This is the same as running the machine in isolation aka the machine running in a javascript environment. The architecture I recommended would not be interacting with the react side because the providers are not mounted in a react root. In Vue.js I have built out unit tests that mount or do partial mounts of vue components. We could find a react library that does react component test and we can have the machine run and the react components run. This would be outside of the playwright runtime. One issue we ran into is the In terms of testing the xstate machine itself, we can build out any number of tests to ensure the machine is working well, actions are being called properly, states are transitioning properly, and any business logic within the actors. Obviously the definition of the machine itself encodes a lot of safety in the code but we can actually test this stuff now. We can unit test the flows to make sure the correct actions are being called and the internal |
Ffr we have this and some tests that use it, see |
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'm really liking this. Thank you for all the thought going into how not just this code but future code should be written. I'm sure we'll have to iron some stuff out but this feels much more solid and in the immediate term the projects load fast again! Thanks for hooking in the command palette to the app actor too it's been floating
import { commandBarActor } from '@src/machines/commandBarMachine' | ||
import { type IndexLoaderData } from '@src/lib/types' | ||
import { engineStreamActor, useSettings, useToken } from '@src/lib/singletons' | ||
import { commandBarActor } from '@src/lib/singletons' |
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: these are from the same file, I'm surprised we don't have a lint rule about combining imports
onSubmit: () => { | ||
refreshPage('Command palette').catch(reportRejection) | ||
export function createAuthCommands({ | ||
authActor, |
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 smart yeah I see the circular deal with these imports
], | ||
}, | ||
onError: { | ||
target: SystemIOMachineStates.idle, |
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.
Alright just something we should keep an eye on. Maybe a toast or a error log could help diagnose if this error ever comes up for a user.
* chore: saving off skeleton * fix: saving skeleton * chore: skeleton for loading projects from project directory path * chore: cleaning up useless state transition to be an on event direct to action state * fix: new structure for web vs desktop vs react machine provider code * chore: saving off skeleton * fix: skeleton logic for react? going to move it from a string to obj.string * fix: trying to prevent error element unmount on global react components. This is bricking JS state * fix: we are so back * chore: implemented navigating to specfic KCL file * chore: implementing renaming project * chore: deleting project * fix: auto fixes * fix: old debug/testing file oops * chore: generic create new file * chore: skeleton for web create file provide * chore: basic machine vitest... need to figure out how to get window.electron implemented in vitest? * chore: save off progress before deleting other project implementation, a few missing features still * chore: trying a different init skeleton? most likely will migrate * chore: first attempt of purging projects context provider * chore: enabling toast for some machine state * chore: enabling more toast success and error * chore: writing read write state to the system io based on the project path * fix: tsc fixes * fix: use file system watcher, navigate to project after creation via the requestProjectName * chore: open project command, hooks vs snapshot context helpers * chore: implemented open and create project for e2e testing. They are hard coded in poor spot for now. * fix: codespell fixes * chore: implementing more project commands * chore: PR improvements for root.tsx * chore: leaving comment about new Router.tsx layout * fix: removing debugging code * fix: rewriting component for readability * fix: improving web initialization * chore: implementing import file from url which is not actually that? * fix: clearing search params on import file from url * fix: fixed two e2e tests, forgot needsReview when making new command * fix: fixing some import from url business logic to pass e2e tests * chore: script for diffing circular deps +/- * fix: formatting * fix: massive fix for circular depsga! * fix: trying to fix some errors and auto fmt * fix: updating deps * fix: removing debugging code * fix: big clean up * fix: more deletion * fix: tsc cleanup * fix: TSC TSC TSC TSC! * fix: typo fix * fix: clear query params on web only, desktop not required * fix: removing unused code * fmt * Bring back `trap` removed in merge * Use explicit types instead of `any`s on arg configs * Add project commands directly to command palette * fix: deleting debugging code, from PR review * fix: this got added back(?) * fix: using referred type * fix: more PR clean up * fix: big block comment for xstate architecture decision * fix: more pr comment fixes * fix: merge conflict just added them back why dude * fix: more PR comments * fix: big ciruclar deps fix, commandBarActor in appActor --------- Co-authored-by: Frank Noirot <[email protected]>
Issue
Implementation
Overall notes about the large PR, frontend architecture will be in the headers below
-1
.npm run circular-deps:diff:nodejs
to see the add and remove of deps easierappMachine
intosingleton.ts
because the AppActor needs the singletons and this will reduce the circular dependencies.rootContext
now :)commandBarActor
now at the root level!!projectCommand
initialization caused some new circular deps.Frontend Architecture
components/Providers/
: If the xstate machine needs to do react stuff, the react provider should listen to the machine and perform the react code. One for web and desktopsystemIO/utils.ts
systemIO/hook.ts
: A set of hooks that can be used throughout the entire codebase when needing to access the systemIOMachine in reactsystemIO/snapshotContext
: A set of sync functions that can be used throughout the entire codebase when needing to access the systemIOMachine state in javascriptFAQS
Q: Is this frontend architecture a hard requirement?
A: No. This is a suggested pattern to help structure our initialization of the Javascript code, the
ReactDOM.createRoot(...
and the data accessing patterns across all the react components within that singlecreateRoot
call. This should be a typical pattern that developers can use, extend, and feel confident using.Always know why you are writing new state management, new loading patterns, new component patterns etc.. and pick the best tool or pattern for the job.
Q: Is this a magic bullet?
A: No. This will help reduce race conditions by having clear ownership of business logic. This will reduce multiple sources of truth. This will reduce circular dependencies. This will improve the initialization of the application (reduces circular dependencies).
Q: Does xstate and react always have to be separate?
A: No, an xstate machine can implement React code but please be sure you know why you are doing this. Does it actually need to be coupled or can you have a separate xstate machine and then a react provider component.
Q: Does every provider need to be in
<Root/>
A: No. If it calls
navigate()
via the react router dom then yes. Otherwise you should be able to put itroot.render(...
inindex.tsx
Q: What react components live the entire application lifecycle?
A:
index.tsx
theroot.render(...
then the<Root/>
in the React router because I fixed theerrorElement
definition.Q: How do we initialize the application without circular dependencies?
A: In the future all the code in
singleton.ts
should be mapped out to initialize in the order of dependencies then we callconst root = ReactDOM.createRoot(...
and pass whatever data we need if required during initialization.Q: Can code live outside React? What about classes?
A: Yes, state management should live outside React (for application level state management). Local state management in components is fine. This is not a strict rule but please be aware why and where you are initializing state. Classes that do custom/dense javascript logic can live outside of React because sometimes the React lifecycle or API does not do what we need. Sometimes you need to just write raw JS code/ DOM code or import a library.
Q: Do I always need to implement an xstate machine for state or use the xstate library?
A: No, use your best judgement on what you are storing, the lifecycle of the data, how it is fetched, and what parts of the code base need to access it. Having calls to
useState
in a simple UI component are completely fine. If you start writing larges parts of business logic, fetching a ton of data withinuseState
you should consider writing it as a global machine if other parts of the system need access to that data.Diagram
Machine documentation