Giter VIP home page Giter VIP logo

xstate-tools's People

Contributors

andarist avatar andreash avatar brunocrosier avatar davidkpiano avatar ericjonathan6 avatar farskid avatar github-actions[bot] avatar jlarmstrongiv avatar mattpocock avatar mellson avatar with-heart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xstate-tools's Issues

Throttle configuration for typegen autosave

With the new typegen feature the extension is doing some "throttled auto save as you type". This can get a bit heavy on the CPU if there's for example a dev-server running in the background watching files and doing recompiles.

Not exactly sure what the best solution would be, but if it would be possible to make the auto save feature configurable that could help.

A workaround is to close any file watchers whilst editing the machine config.

And I must say that the typegen support is probably the biggest leap in developer experience I've ever encountered! Really impressed with what you've achieved. Great work!

empty canvas after switching to new vscode extension

no machine is rendered in the new visualizer tab either when using:

  • createMachine({...})
const promiseMachine = createMachine({
  id: 'promise',
  initial: 'pending',
  states: {
    pending: {
      on: {
        // state transition (shorthand)
        // this is equivalent to { target: 'resolved' }
        RESOLVE: 'resolved',

        // state transition (object)
        REJECT: {
          target: 'rejected',
        },
      },
    },
    resolved: {
      type: 'final',
    },
    rejected: {
      type: 'final',
    },
  },
})

or

  • model = createModel(); model.createMachine({...})
import { createModel } from 'xstate/lib/model'
import { createMachine } from 'xstate'

interface Config {
  featureIsEnabled?: boolean
}

const userFlowModel = createModel(
  {
    config: {} as Config,
  },
  {
    events: {
      TEST_SELECTED: () => ({}),
    },
  }
)

export const userFlowMachine = userFlowModel.createMachine(
  {
    id: 'user-flow',
    initial: 'selectTest',
    states: {
      selectTest: {
        on: {
          TEST_SELECTED: 'test',
        },
      },
      test: {},
      results: {},
    },
  },
  {
    actions: {},
  }
)

Typegen doesn't support events name as enum

Maybe linked to the same root cause as #32?

I usually set my machines states/events/guards/actions name as enums, but migrating to Typegen, I noticed that the schema.events types doesn't support enums.

Considering the following state machine:

export enum States {
  Initial = 'initial',
  Success = 'success',
}

export enum Events {
  Submit = 'SUBMIT',
}

interface MachineContext {}

type MachineEvents = { type: Events.Submit }

export const myMachine = createMachine(
  {
    tsTypes: {} as import('./my.machine.typegen').Typegen0,
    schema: {
      context: {} as MachineContext,
      events: {} as MachineEvents,
    },
    id: 'myMachine',
    initial: States.Initial
    states: {
      [States.Initial]: {
        on: {
          [Events.Submit]: {
            target: States.Success,
            actions: 'onSubmit',
          },
        },
      },
      [States.Success]: {
        type: 'final',
      },
  },
  {
    actions: {
      onSubmit: assign((context, event) => ({ /* ... */ })),
  },
});

The event argument of the onSubmit action has the never type. But if I change the MachineEvents for:

type MachineEvents = { type: 'SUBMIT' }

It works as expected.

Inspector is blank for machines with multiple global actions

When using the inspector in vs code the inspector panels goes blank when the machine contains multiple global actions.

To reproduce open the inspector in vscode with the following machine

import { createMachine } from 'xstate';

const machine = createMachine({
  id: 'machine',
  on: {
    A: { actions: 'ON_A' },
    B: { actions: 'ON_B' },
  },
  initial: 'HELLO',
  states: {
    HELLO: {},
  },
});

The result is shown in the following screenshot
Screenshot 2022-02-10 at 16 10 36

This doesn't appear to be an issue in the visualiser on stately.ai as shown here

The expected result would be to display what we see in the stately visualiser

Visualiser chooses incorrect transition / incorrect guard

Given the following machine, pressing the transition to b actually goes to a. In general the visualiser respects the order of transitions in the array, I think it should respect the transition you click and ignore guards.

createMachine({
	id: 'bug',
	initial: 'idle',
	states: {
		idle: {
			on: {
				some_event: [
					{
						target: 'a',
						cond: 'someCOnd',
					},
					{
						target: 'b',
					},
				],
			},
		},
		a: {
			type: 'final',
		},
		b: {
			type: 'final',
		},
	},
});

See video below that demonstrates the issue

Screen.Recording.2021-10-12.at.13.23.35.mov

Feature request: capability to pan the machine in the visualizer

img

Hello, in https://stately.ai/viz, you can pan the visualized machine with the hand button as shown above. However, in the VSCode visualizer, there is no such button. If the visualized machine is very long, we either have to zoom out very far and not be able to read the text, or we will have to zoom in and not be able to see parts of the machine.

Is it possible to implement a panning capability?

Thank you.

Typegen file not created on Linux

On:

  • Linux (non Flatpak)
  • XState v4.29.0
  • @xstate/react v2.0.0
  • XState VSCode v1.4.1

... The Typegen file is not generated and the tsTypes: {}, line has the following TS error:

Type '{}' is not assignable to type 'TypegenConstraint | undefined'.
  Property ''@@xstate/typegen'' is missing in type '{}' but required in type 'TypegenEnabled'.ts(2322)

I don't have any error in VS Code logs, as in #40 though...

What could I give you to better investigate?

"Open Visual Editor" in Code Lens not Syncing Changes in Windows

Based on multiple reports on Discord (1, 2), I created this issue based on @mattpocock's request.

Problem

When Launching the Editor on Windows via the Code Lens Feature, the Editor works fine, but no changes are back-propagated to the file.

Workaround

Everything works fine if the Editor is opened via the command palette.

Investigation

I did some investigation, (inspired by #41) and I am pretty sure that the problem is in:
https://github.com/statelyai/xstate-vscode/blob/0f0966cd478a02e66a9935c1d6ce0668eab3fe29/server/src/server.ts#L165-L168
because it handles the creation of the Editor a little bit different than
https://github.com/statelyai/xstate-vscode/blob/0f0966cd478a02e66a9935c1d6ce0668eab3fe29/client/src/initiateEditor.ts#L212-L217
(where it works). The main difference is the handling of uri creation, which is a problem in VSCode Language Server Node on Windows. The problem is already documented in microsoft/vscode-languageserver-node#105.

Solution

Is there a pretty quick way to run the extension in debug mode/run this repo? I would love to add appropriate samples for MacOS and Windows so that this URI stuff can be fixed once and for all.


And a huge ❤ for all the work put into this extension, it just feels like one would expect it!

Typegen doesn't compute actions listed in state `after` prop

When an action is only listed in state.after props, the following error myCustomAction is never used in the machine definition is marked in the action implementation as the action is not included in the typegen file

createMachine({
  ...
  myIntervalState: {
    after: [
      { delay: 1000, target: 'myInternalState', actions: ['myCustomAction']
    ]
  }
  ...
}, {
  actions: {
    myCustomAction: (context) => {...}
  }
})

[Bug] Custom guard act as if never used

Problem:
getting a xxx is never used in the machine definition when using custom guards (https://xstate.js.org/docs/guides/guards.html#custom-guards)

Context:
Using the VS-code extension version 1.2.1 and xstate version 4.23.0.

Repro:
When pasting this in the parser (https://xstate-parser-example-site.vercel.app) :

createMachine(
    {
        initial: "start",
        states: {
            start: {
                on: {
                    MOVE: [
                        { target: "end", cond: { type: "customGuard", param: 123 } },
                        { target: "end", cond: "workingGuard" },
                    ],
                },
            },
            end: {},
        },
    },
    { guards: { customGuard: (ctx) => false, workingGuard: (ctx) => true } }
);

We can see that the custom guard is noted as anonymous

Ensure a service has an id when it needs one

Sometimes I do:

send('EVENT', { to: 'myService' })

and I've invoked myService without an id.

invoke: { src: 'myService' }

Then it takes me a few hours to figure out why my event is not arriving.

If there's a way to notice that you're sending an event to a service, but that there is no service in the file that matches that id, that would be amazing!! 🙏

Idea: Link to stately editor/visualizer

It would be nice to have a link to stately in the code (like image below) or even on the editor tab where the link would navigate to the stately.ai site.

The idea is that we could update the machine in vscode or on the site and everything would be in sync. There could be some kind of mechanism that when someone changes in vscode, it triggers an update on stately.ai, and when someone does a change on stately, it triggers a commit on the repo.

image

Another thing is the base64 representation. Although I understand its usefulness, it adds noise to the machine. I could see it in another file with state machines base64s (something similar to package-lock.json) or just keep that information on stately.ai.

Anyway, hope this can be helpful and can't wait to see what you come with! This is really starting to look like a tipping point for state machines.

Unable to evaluate serialized guards in eventless transitions

The following code yields the error

Unable to evaluate guard 'test' in transition for event '' in state node '(machine).someState':
guard.predicate is not a function
createMachine(
  {
    initial: "someState", // also, the error disappears if the machine doesn't have an initial state 🤔
    states: {
      someState: {
        always: { cond: "test", target: "otherState" },
      },
      otherState: {},
    },
  },
  {
    guards: {
      test: () => true,
    },
  }
);

It works fine if I inline the guard instead. Also, serialized guards works fine in regular event transitions.

Support state and event as enum value

I'm using enums to type my machine states and events. It seem like the viz is only able to determine them when they are plain string

See above, [AuthStates.Forgot] is not in the viz, while idle , login and register are.
Same for the events, as you can see from login state I can only receive register event

ext-enum

"xstate.edit-code-lens not found" when trying to open visual editor

I had an old version installed earlier. I tried to delete the old version and install fresh, but with the same results. It feels like there are things left over from the old version, causing the new version to fail or something.

image

Extension host logs:

On plugin activation

[2022-02-08 15:22:47.610] [exthost] [error] Error: command 'xstate.visualize' already exists
	at u.registerCommand (/opt/visual-studio-code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:93:28683)
	at Object.registerCommand (/opt/visual-studio-code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:107:30423)
	at initiateVisualizer (/home/nbostrm/.vscode/extensions/statelyai.stately-vscode-1.5.16/client/dist/index.js:155145:57)
	at activate (/home/nbostrm/.vscode/extensions/statelyai.stately-vscode-1.5.16/client/dist/index.js:155269:5)
	at async Promise.all (index 0)
	at async w.$activate (/opt/visual-studio-code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:98:21810)

When trying to run "XState: Open visual editor:

[2022-02-08 15:23:20.349] [exthost] [error] Error: command 'xstate.edit-code-lens' not found
    at b._tryExecuteCommand (vscode-file://vscode-app/opt/visual-studio-code/resources/app/out/vs/workbench/workbench.desktop.main.js:1489:3364)
    at vscode-file://vscode-app/opt/visual-studio-code/resources/app/out/vs/workbench/workbench.desktop.main.js:1489:3245
    at processTicksAndRejections (internal/process/task_queues.js:93:5) xstate.edit-code-lens undefined

image

About Visual Studio Code:

Version: 1.64.0
Commit: 5554b12acf27056905806867f251c859323ff7e9
Date: 2022-02-03T04:23:11.224Z
Electron: 13.5.2
Chromium: 91.0.4472.164
Node.js: 14.16.0
V8: 9.1.269.39-electron.0
OS: Linux x64 5.16.4-arch1-1

Visual Editor erases "description" field on states

The visual editor allows you add description field:

image
image

But when you close and reopen the editor the description is gone:
image

Furthermore as soon as you make any change to the statechart in the visual editor the description is erased from the machine definition

Maximum call stack size exceeded error

I'm getting Maximum call stack size exceeded error when using always to go back and forth between states, even though they have conds:

    states: {
      noneSelected: {
        always: {
          target: 'someSelected',
          cond: (ctx) => ctx.selected.length > 0,
        },
      },
      someSelected: {
        on: {
          PRINT: { actions: 'printSelected' },
          COPY: { actions: 'copySelected' },
          DESELECT_ALL: { actions: 'clearSelected' },
        },
        always: {
          target: 'noneSelected',
          cond: (ctx) => ctx.selected.length === 0,
        },
      },
    },

"Open Inspector" never shows

After installing the extension and visiting machine files, no "Open Inspector" link shows. I restarted VSCode for good measure. I even attempted different machines (I have quite a few).

I'm on MacOS Big Sur on an M1 architecture.

Here's an obfuscated version of the machine:

import { assign, createMachine } from "xstate";

export const dashboardMachine = createMachine(
  {
    id: "dashboard",
    initial: "inactive",

    context: {
      list1: [],
      list2: [],
    },

    states: {
      inactive: {
        on: {
          ENTER: "active",
        },
      },

      active: {
        type: "parallel",

        on: {
          EXIT: "inactive",
        },

        states: {
          list1: {
            initial: "loading",

            states: {
              loading: {
                invoke: {
                  src: "fetchList1",
                  onDone: {
                    target: "idle",
                    actions: ["assignList1"],
                  },
                  onError: "errorLoading",
                },
              },
              errorLoading: {},
              idle: {},
            },
          },

          list2: {
            initial: "loading",

            states: {
              loading: {
                invoke: {
                  src: "fetchList2",
                  onDone: {
                    target: "idle",
                    actions: ["assignList2"],
                  },
                  onError: "errorLoading",
                },
              },
              errorLoading: {},
              idle: {},
            },
          },
        },
      },
    },
  },

  /*
   * Options
   */
  {
    actions: {
      assignList1: assign((context, event) => ({
        // @ts-expect-error
        list1: event.data,
      })),
      assignList2: assign((context, event) => ({
        // @ts-expect-error
        list2: event.data,
      })),
    },

    services: {
      fetchList1: async (context, event) => {
        return ['first', 'list'];
      },
      fetchList2: async (context, event) => {
        return ['second', 'list'];
      },
    },
  }
);

Inspector/editor does not auto-update on change

User story
When I save my document, I expect the XState visualizer to automatically refresh to reflect the current machine configuration.

Expected
Saving a document immediately refreshes the visualizer tab.

Actual
Nothing happens. I must instead close and reopen the visualizer, or click the "Open Inspector" tab multiple times for it to rerender correctly.

Details

  • Extension - v1.5.11
  • VSCode - 1.64.0
  • XState - 4.29.0
  • Old extension removed? - Yes

How to reproduce
(This GIF shows that the tab is particularly buggy, with it failing to load multiple times)

inspector

  • Open a file that supports machines (I tested with with JS, TSX, and TS)
  • Using createMachine, write some configuration, save the file
  • Click on "Open Inspector"
  • Change a value, hit save, nothing happens.

From this example:

import { createMachine } from 'xstate';


export const machine = createMachine({
  id: "example",
  initial: "one",
  states: {
    one: {
      on: {
        ONE: "one",
        TWO: "two",
        THREE: "three"
      }
    },
    two: {
      on: {
        ONE: "one",
        TWO: "two",
        THREE: "three"
      },
    },
    three: {
      on: {
        ONE: "one",
        TWO: "two",
        THREE: "three"
      },
    },
  },
});

Typegen file not created on Windows

VSCode developer log for "Window" shows the following when saving a machine:

[2022-01-27 16:34:50.561] [renderer1] [error] UNKNOWN: unknown error, stat '\\c%3A\dev\project\src\index.ts': Error: UNKNOWN: unknown error, stat '\\c%3A\dev\project\src\index.ts'

And no typegen file is created. Probably a path resolution thing?

Editor/Visualizer buttons don't appear when there are warnings

If I copy the code from transitions to VS code, it doesn't show the buttons to open the editor and viz. It looks like it happens when there are warnings (at least the empty string transition warning).

image

As soon as I change the "" to "a" it shows the buttons.

image

It would be helpful to always see the buttons or at least the warning messages in place of the buttons. It looks like the extension is not working.

Thanks and keep up the great work!

State keys with spaces not interpreted as string literals

The following code yields the error Object keys in states property must be string literals:

import { createMachine } from "xstate";

createMachine({
  states: {
    "state with spaces": {
      on: {
        "event with spaces": {
          target: "someOtherState",
        },
      },
    },
    someOtherState: {}
  },
});

Also, thanks for making this! Very exciting! 🚀

[TypeScript] typegen creating output which conflicts with @typescript-eslint/ban-types

Description

Typegen output is offending @typescript-eslint/ban-types whose mission statement is

Some builtin types have aliases, some types are considered dangerous or harmful. It's often a good idea to ban certain types to help with consistency and safety.

-- README

Expected Result

Typegen output should not use incorrect types which are flagged by the @typescript-eslint/ban-types rule

Actual Result

The specific error is:

Don't use `{}` as a type. `{}` actually means "any non-nullish value".
- If you want a type meaning "any object", you probably want `Record<string, unknown>` instead.
- If you want a type meaning "any value", you probably want `unknown` instead.
- If you want a type meaning "empty object", you probably want `Record<string, never>` instead.e

And can occur on invokeSrcNameMap, eventsCausingServices, eventsCausingGuards, and eventsCausingDelays:

image

Reproduction

Typegen doesn't run on codesandbox, but the following machine will trigger the above error on [email protected]:

import { createModel } from 'xstate/lib/model';

export const testModel = createModel(
  {
    name: null as null | string,
  },
  {
    events: {
      setName: (name: string) => ({
        name,
      }),
      reset: () => ({}),
    },
  },
);

export const surveyFormMachine = testModel.createMachine({
  tsTypes: {},
  id: 'test',
  initial: 'idle',
  context: testModel.initialContext,
  states: {
    idle: {},
  },
  on: {
    reset: {
      actions: 'resetContext',
    },
    setName: {
      actions: 'setName',
    },
  },
});

Additional context

XState 4.29.0
statelyai.stately-vscode 1.5.6

forwardTo actions do not render correctly

User story
When using the forwardTo(<id>) action in a machine, I expect to see DO / send to <id> in the rendered machine.

Expected

The id appears in the DO handler in the event.

image

Actual

The id does not appear in the DO handler, and the handler says send instead of send to.

image

Machine Highlights with Semantic Tokens

This issue corresponds to the idea of special highlights in machine definitions that is outlined on Twitter: https://twitter.com/_maciej/status/1442463662464192515

I experimented with semantic highlighting yesterday. Since the XState language server has a better understanding of the machines, highlighting should be provided by the language server. The VS Code documentation1 appears to explain an implementation that is editor based, but semantic token are also supported by the LSP2. At the moment, I have yet to find an example/documentation for the vscode-languageserver library so it is not just a "guess how it works" implementation.

More importantly, I am not sure if we can currently support this use case with the parsed machine results. My idea has been to grab all locations of state names and transition names in the document from the parsed results. The parsed results do not contain such information at the moment, right? At least I did not find information about the location of state names and transition names in the object.

On a side note: State and transition names are specially highlighted in the Stately Viz if the names use CamelCase3:

image

Footnotes

  1. https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide

  2. https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens

  3. https://stately.ai/viz/bea3ab1f-b1c3-4d6b-adc2-f4c64d52fd8d

Add command palette action for opening visualiser

As highlighted by another issue #7; If code lens is not enabled, the clickable magnifying glass will not be visible for users to click on and open the visualiser.

To get around this, a command could be added so that the visualiser can be opened from a command palette shortcut. For example: cmd/ctrl + shift + p and then entering a command such as visualiser or start vis.

Validation for inline invokes

Inline invokes are successfully loaded into the Editor (as they don't create linting errors) but when syncing them back to the code the Editor writes this:

      invoke: {
        src: '_inline',
      },

We should prevent loading such problematic machines to avoid this stuff being written back to a source code.

Rename machine event keys when renaming the model's events

When renaming events on a model (Rename Symbol / F2), VSCode doesn't rename the corresponding event keys in the machine defintion.

This would be a nice quality-of-life improvement when using createModel.

Example

import {createMachine} from 'xstate'
import {createModel} from 'xstate/lib/model'

const model = createModel(
  {
    name: 'Matt',
  },
  {
    events: {
      nameChange: (name: string) => ({name}),
    },
  },
)

const machine = model.createMachine(
  {
    on: {
      nameChange: {actions: 'setName'},
    },
  },
  {
    actions: {
      setName: model.assign(
        {
          name: (_context, event) => event.name,
        },
        'nameChange',
      ),
    },
  },
)

Using the VSCode Rename Symbol feature on nameChange inside the model definition should also rename the event key inside the on definition and in the second argument to model.assign.

Events do not show up if they exist in another file.

I often create a machine.types.tsx file that contains all of my states, events, and the type of machine. I then use these values/enums in separate machines based on platform...

Example...
exampleMachine.types.tsx - exports enums for States, types for events, and the type of the machine.

export enum Events {
  event1 = 'EVENT_1',
  event2 = 'EVENT_12',
  ....
}

type EventTypeSchema =
  | Events.event1
  | Events.event2;

export interface MyMachineEvents extends EventObject {
  type: EventTypeSchema;
}

export interface MachineContext {}

export type TMyMachine = StateMachine<
  MachineContext,
  any,
  MyMachineEvents
>;

exampleMachine.native.tsx - This will actually create the machine for iOS and Android (react native) that was typed in exampleMachine.types.tsx, utilizing the States enum from the same file.

exampleMachine.web.tsx - This will actually create the machine for web that was typed in exampleMachine.types.tsx, utilizing the States enum from the same file. This machine may behave a bit differently, because it is on another platform, but it still adheres to the same contract/types, so any parent machine that "uses" it has type safety.

Issue

The visualizer is not drawing the events because the parser doesn't know about them, because they live in another file.

Would it be possible to extend the functionality of the xstate-parser to search import paths for these events/states?

Thanks so much for the wonderful tool!

Supporting inline cond/action implementations?

Hi there! Started a new project with xstate recently and have been really enjoying the experience!

Though I'm a bit disappointed with not being able to use the visualizer/editor due to my use of inline conds/actions. I find that the indirection from string-based conds/actions adds too much friction to be worthwhile for my use case where I have no need to ever serialize the machine config (are there other benefits that I'm missing?).

I originally assumed this is because the editor needs to serialize the machine to read and edit it, but recently learned it's actually smarter than that and works with the AST directly, in which case I'd love to learn more about what actual blockers are there to supporting inline implementations.

Throwing some random thoughts out there:

  • If it's more feasible to support the visualization side without the editing side, I can totally live with that!

  • Could an alternative API for providing inline implementations help? Maybe something that accepted an object with id instead of a function so it can be visualized with the id?

Please excuse my ignorance if these are things y'all have already thought about (which I assume is very likely the case 😅 ).

Transitions that contain conditions with enums fail to render

The following machine does not render anything in the visualizer...

enum States {
  init = 'init',
  done = 'done',
}
enum ConditionNames {
  One = 'One',
}
const machine = createMachine({
  initial: States.init,
  states: {
    [States.init]: {
      on: {
        '': {
          cond: ConditionNames.One,
          target: States.done,
        },
      },
    },
    [States.done]: {},
  },
});

The same machine renders just fine if I remove the condition...

enum States {
  init = 'init',
  done = 'done',
}
enum ConditionNames {
  One = 'One',
}
const machine = createMachine({
  initial: States.init,
  states: {
    [States.init]: {
      on: {
        '': {
          //cond: ConditionNames.One,
          target: States.done,
        },
      },
    },
    [States.done]: {},
  },
});

image

It seems like the parser is not accounting for enums when it hits a condition. Enums seem to work fine for state nodes.

Autocomplete not working for me

Not entirely sure how to get to the bottom of this.

The extension is correctly telling me that the state doesn't exist as I type, I just don't get any autocomplete suggestions.

Tried disabling all extensions except this one and same behavior.

Untitled.mov

turn off linting seperately

Having my entire code window underlined in red squiggliest every time I type is super distracting. I wound up disabling the entire exertion to get rid of it.

Support cross module parsing

Config and options have to be written in the same file that declares the machine, to be found by the extension.

Example:

The visualizer can't find the machine
ext-import

The visualizer can find the machine
ext-no-imports

Machines with parametric send don't work

The following machine does not render anything in the visualizer...

export const loadingFSMSchema = createMachine({
  initial: 'idle',
  states: {
    idle: {
      entry: [actions.log((context) => '--- [loadingFSM] --- idle '), send((context) => 'aa')],
      after: {
        4000: {
          target: 'finalState',
          // actions: send('LOADING_COMPLETED'),
        },
      },
    },

    finalState: {
      entry: [actions.log('--- [loading FSM] --- finalState '), send('LOADING_COMPLETED')],
      type: 'final',
    },
  },
  on: {
    '*': {
      actions: actions.log('ahahahhdsjkl'),
    },
  },
});

Same machine does render if I don't use parametric send send((context) => ...):

export const loadingFSMSchema = createMachine({
  initial: 'idle',
  states: {
    idle: {
      entry: [actions.log((context) => '--- [loadingFSM] --- idle '), send('aa')],
      after: {
        4000: {
          target: 'finalState',
          // actions: send('LOADING_COMPLETED'),
        },
      },
    },

    finalState: {
      entry: [actions.log('--- [loading FSM] --- finalState '), send('LOADING_COMPLETED')],
      type: 'final',
    },
  },
  on: {
    '*': {
      actions: actions.log('ahahahhdsjkl'),
    },
  },
});

Setting multiple targets does not render correctly

User story
When setting multiple targets for an event, I expect the machine to render with an EVENT object pointing to each state, and interacting with that object causes all transitions to occur.

Expected
expected

Actual
actual

  • EVENT object is rendered at the top level
  • EVENT object is non-interactive, and attempting to interact with it does not cause the expected transitions

Casting MachineConfig breaks the inspector

User story:
When I inline cast my machine's config, I expect the extension to behave as normal.

Expected behaviour:

  • Open inspector prompt appears.
  • If the inspector is open, it should update.

Actual:

  • Open inspector prompt is not visible.
  • If the inspector is open, it stops updating.

Steps to reproduce:

const myModel = createModel({});

export type MyContext = ContextFrom<typeof myModel >;
export type MyEvent = EventFrom<typeof myModel>;

type MyConfig = MachineConfig<MyContext , any, MyEvent >;

// Either of these break
myModel.createMachine({ id: "HelloWorld" } as MyConfig);
myModel.createMachine(<MyConfig>{ id: "HelloWorld" });

// This works
const myConfig: MyConfig = { id: "HelloWorld" };
myModel.createMachine(myConfig);

Problem autocompleting with dots

Thanks a lot @mattpocock !

Testing the autocompletion, it only works properly before a dot in a target state. When autocompleting after a dot, the word is repeated. Let me show you a video so it's clearer:

autocomplete_dot.mov

Not sure if this is even a VSCode problem?

Thanks!!

Actions or guards are not recognized when inside of delayed transitions

The following code shows some errors

import { assign, createMachine } from "xstate";

type CardValue = string;
type CardIndex = number;

type GameContext = {
  flippedCards: Array<CardIndex>;
  board: Array<CardValue | undefined>;
  rows: number;
  columns: number;
};

type FlipCardEvent = {
  type: "FLIP_CARD";
  index: CardIndex;
};

type GameEvent = FlipCardEvent;

const flipCard = assign<GameContext, GameEvent>((context, event) => ({
  flippedCards: context.flippedCards.concat(event.index),
}));

const untapCards = assign<GameContext, GameEvent>(() => ({
  flippedCards: [],
}));

const removeFlippedCards = assign<GameContext, GameEvent>((context) => {
  const [first, second] = context.flippedCards;
  let updatedBoard = context.board;
  updatedBoard[first] = undefined;
  updatedBoard[second] = undefined;

  return {
    flippedCards: [],
    board: updatedBoard,
  };
});

const flippedCardsAreMatching = (context: GameContext) => {
  const [first, second] = context.flippedCards;
  return context.board[first] === context.board[second];
};

const hasNoAvailableCards = (context: GameContext) => {
  return context.board.every((card) => card === undefined);
};

export const gameMachine = createMachine<GameContext, GameEvent>(
  {
    id: "Game",
    initial: "idle",
    context: {
      flippedCards: [],
      board: ["a", "b", "a", "b"],
      columns: 2,
      rows: 2,
    },
    states: {
      idle: {
        on: {
          FLIP_CARD: {
            target: "flipedFirstCard",
            actions: "flipCard",
          },
        },
      },
      flipedFirstCard: {
        on: {
          FLIP_CARD: {
            target: "checkResult",
            actions: "flipCard",
          },
        },
      },
      checkResult: {
        after: {
          1000: [
            {
              target: "success",
              cond: "flippedCardsAreMatching",
              actions: "removeFlippedCards",
            },
            { target: "fail", actions: "untapCards" },
          ],
        },
      },
      success: {
        always: [
          { target: "end", cond: "hasNoAvailableCards" },
          { target: "idle" },
        ],
      },
      fail: {
        always: "idle",
      },
      end: {
        type: "final",
      },
    },
  },
  {
    actions: {
      flipCard,
      removeFlippedCards,
      untapCards,
    },
    guards: {
      flippedCardsAreMatching,
      hasNoAvailableCards,
    },
  }
);

Screen Shot 2021-09-10 at 20 45 25

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.