statelyai / rfcs

RFCs for XState and Stately tools
44 stars 5 forks source link

Single-file XState definitions #3

Open mattpocock opened 3 years ago

mattpocock commented 3 years ago

From a Slack conversation we had yonks ago:

A mad Sunday-before-I-go-back-to-work thought:

I've been thinking about a possible VSCode integration with a visual builder/linting tool. As we know, the biggest difficulty with this is extracting the machines from Javascript. @Andarist's proposal - to extract the machine in pure TS - may work, but I wanted to propose something else which feels a bit more out-there.

Quite a lot of voices in the community write their machine definitions in JSON/YAML. People seem to like thinking of their XState machines as static configuration - this includes me. If this were the only way you could write state machine definitions, it would be way easier to extract - you could just read the JSON and pump it into a visualiser.

But there are problems with this. You can't use various useful XState action creators, because it's in JSON. You can't colocate your TS type definitions with your machine.

What about an SFC pattern? Imagine a .xstate file which looked like this:

// Schema is declared in JS, with all XState actions (choose, assign etc) available globally. No imports allowed, and only one export default allowed
<schema>
  export default {
    id: 'machine',
    initial: 'running',
    states: {
      running: {
        on: {
          STOP: 'stopped'
        }
      },
      stopped: {
        entry: ['reportStopped']
      }
    }
  }
</schema>
// Options (optional) can be declared in JS/TS,
// with imports
<options>
  export default {
    actions: {
      reportStopped: () => {
        console.log('Stopped');
      }
    }
  }
</options>
// Typedefs can be declared in TS, with imports
<types>
  export type Event = {
    type: 'STOP'
  };
  export type Context = {};
</types>

Personally, I would use the heck out of this. Imagine - you enter the file, VSCode knows you're looking at a machine definition, and it opens it up for you in the inspector/visualiser. The visual builder could make direct changes to the schema safely. It also opens up other possibilities, such as only compiling the parts of XState you actually use.

Trouble is - it's mad. It's a lot of work. But I thought I'd share in case it sparks some other ideas.

ChrisShank commented 3 years ago

Would Lucy or other statechart DSLs solve this problem?

mattpocock commented 3 years ago

Not wholly - the appeal of the above is that you can edit the <schema /> separately to the implementation. This allows for really easy integration of the visual builder with code.

Lucy is an alternative to the visual builder, not a compile target of the visual builder.