Skip to content

Version Packages (alpha) - #5813

Merged
davidkpiano merged 1 commit into
nextfrom
changeset-release/next
Oct 19, 2026
Merged

davidkpiano merged 1 commit into
nextfrom
changeset-release/next

Conversation

@github-actions

@github-actions github-actions Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to next, this PR will be updated.

⚠️⚠️⚠️⚠️⚠️⚠️

next is currently in pre mode so this branch has prereleases rather than normal releases. If you want to exit prereleases, run changeset pre exit on next.

⚠️⚠️⚠️⚠️⚠️⚠️

Releases

xstate@6.0.0-alpha.70

Major Changes

  • ceeebb0: ActorRefFrom<T> accepts actor logic only, and ActorRefFromLogic<T> is removed. Replace ActorRefFromLogic<T> with ActorRefFrom<T>. Pass the logic type instead of a promise, an actor ref, or a function returning logic:

    // Before
    type Ref = ActorRefFromLogic<typeof machine>;
    type AsyncRef = ActorRefFrom<Promise<User>>;
    
    // After
    type Ref = ActorRefFrom<typeof machine>;
    type AsyncRef = ActorRefFrom<typeof loadUser>;

    ActorRefFrom<typeof machine> refs return the fully typed machine snapshot from getSnapshot(), including context, value and matches('#id').

  • ceeebb0: State keys cannot contain an unescaped ., which separates path segments. Creating a machine with such a key throws State key "foo.bar" contains "." — nest the states or escape it as "foo\\.bar". To use a literal dot, write the key escaped. The escaped form is then the key everywhere: state values, implicit ids, matches(...), targets and persisted snapshots. It never collides with a nested foo → bar.

    // Before
    states: { 'foo.bar': {} }, on: { GO: { target: 'foo\\.bar' } }
    
    // After
    states: { 'foo\\.bar': {} }, on: { GO: { target: 'foo\\.bar' } }
    // snapshot.value === 'foo\\.bar'

    Two implicit state ids can no longer coincide, and any duplicate state id now throws.

  • 39d3b5c: # targets, snapshot.matches('#…') and @xstate.stateIn guards resolve by exact state id. The text after # is a state's whole id, either its explicit id or its implicit id (the path from the root, prefixed by the machine id). It is no longer split into an id followed by a relative path. Dots in explicit ids are matched as written, without escaping.

    // `wizard` has `id: 'flow'` in a machine with `id: 'shop'`
    
    // Before
    browsing: { on: { review: { target: '#flow.review' } } }
    
    // After: the target's full implicit id, or give it its own `id`
    browsing: { on: { review: { target: '#shop.wizard.review' } } }

    An unknown id throws when the machine is created. When the old id-plus-path form resolves, the error names the target's id:

    No state has id "flow.review". Use "#shop.wizard.review", or give that state an id.
    

    Typed # targets and matches('#…') accept only whole ids.

  • ceeebb0: The root xstate entry no longer exports type-level helpers: TODO, IsAny, IsNever, Equals, Cast, Compute, Prop, HomomorphicOmit, LowInfer, DoNotInfer, SingleOrArray, MaybeLazy and AnyFunction. Define equivalents in your own code if you used them. ConditionalRequired, IsNotNever and NonReducibleUnknown remain exported because emitted declarations reference them, and are marked @experimental.

    ActorOptions no longer has the undocumented parent option. Create child actors with invoke, spawn(...) or enq.spawn(...).

  • ceeebb0: Implicit state and invoke ids no longer use the (machine) placeholder.

    • A state's implicit id is its path from the root joined by ., prefixed by the machine id when there is one: shop.checkout.payment for id: 'shop', and checkout.payment without an id (previously (machine).checkout.payment).
    • machine.id and the root state's id are '' for a machine without an id. # cannot reference that root; give the machine an id to target it as #shop.
    • An unnamed invoke's id is <stateId>:<index>: loading:0, loading:1, shop.checkout:0. A root invoke is :0, or shop:0 with a machine id (previously 0.(machine).loading). Anonymous spawned actors keep x:<n>, and generated spawn ids skip ids already held by an invoke.
    • An explicit state id that equals another state's id throws when the machine is created.
    • Error messages name the machine instead of machine '(machine)'.
    const machine = createMachine({
      initial: 'loading',
      states: { loading: { invoke: { src: fetchUser } } }
    });
    
    createActor(machine).getSnapshot().children; // { 'loading:0': ... }
    machine.getStateNodeById('#loading').id; // 'loading'

    Persisted snapshots that reference (machine).… state ids or 0.(machine).… child ids do not restore; migrate them with machineVersions.

  • ceeebb0: Children invoked with inline logic no longer get a synthetic source name (xstate.invoke.<index>.<stateId>). Their persisted entries omit src, and restoring resolves them through the invoke definition with the same id among the restored active states. Restoring fails with a descriptive error when no active state, or more than one, invokes that id. Children invoked with a registered name (src: 'fetchUser') keep persisting that key, and remote children still require one.

    const machine = createMachine({
      id: 'shop',
      initial: 'loading',
      states: {
        loading: { invoke: { id: 'fetch', src: fetchUser } }
      }
    });
    
    createActor(machine).start().getPersistedSnapshot().children.fetch;
    // { address: 'shop/fetch', snapshot: {...} }, with no `src`

    Snapshots persisted by earlier alphas that carry src: 'xstate.invoke.…' no longer restore; remove that src or migrate them with machineVersions.

  • ceeebb0: Bare string transition values throw when the machine is created, in every build. This matches the types and machineFromJSON, which already rejected them. It covers on, after, always, onDone, onError, onTimeout, and invoke onDone/onError/onSnapshot/onTimeout. initial stays a string key, and xstate/fsm still accepts string targets.

    // Throws: Transition for "GO" in state "idle" is the string "next". Use { target: 'next' }.
    on: { GO: 'next' }
    
    // Use
    on: { GO: { target: 'next' } }

    xstate-codemod migrate (the string-targets transform) rewrites these.

  • ceeebb0: invoke requires input when the invoked actor logic requires input, matching createActor(logic, { input }) and enq.spawn(logic, { input }). This applies to logic values, registered source names and src functions, in createMachine, setup(...).createMachine and setup(...).createStateConfig. Logic whose input type accepts undefined (no schemas.input, or an optional input schema) can still omit it.

    const child = createMachine({
      schemas: { input: z.object({ userId: z.string() }) }
    });
    
    createMachine({
      // Type error: This actor logic requires input. Add an `input` to this invoke.
      invoke: { src: child }
    });
    
    createMachine({
      invoke: { src: child, input: ({ context }) => ({ userId: context.userId }) }
    });

    enq.spawn(logic) without required input now reports Expected 2 arguments instead of a mismatch against the source-name overload.

  • ceeebb0: A machine that declares version must also declare id, because persisted snapshots record the machine as { id, version }. createMachine, setup(...).createMachine and MachineJSON report a missing id as a type error, and creating such a machine throws Machine with version '2' must declare an id. Machines without a version keep id optional.

    // Before
    createMachine({ version: '2', initial: 'idle', states: { idle: {} } });
    
    // After
    createMachine({
      id: 'order',
      version: '2',
      initial: 'idle',
      states: { idle: {} }
    });

Patch Changes

  • ceeebb0: # transition targets type-check against implicit state ids as well as explicit ones: target: '#checkout.payment', or '#shop.checkout.payment' for a machine with id: 'shop'. Unknown ids are still type errors. At runtime, a # target can name a whole implicit id below a state with an explicit id, such as '#wizard.step' when wizard has id: 'flow'.

  • ceeebb0: enq.spawn(...) returns an inert actor ref while a transition is only evaluated, such as by snapshot.can(event) or when resolving conflicting transitions in parallel states. The ref has the id (and, when the parent is known, the address) the real spawn would get, an undefined sessionId, a stable getSnapshot(), a no-op send(), and toJSON() returning { $actor: address }. Previously it was a bare { id } object.

  • ceeebb0: createActor(machine, { snapshot }) reports a persisted snapshot that cannot represent a state as an 'error' snapshot with an InvalidSnapshotError, instead of starting an unusable actor. This covers snapshots that are not objects, have no value or an invalid one (not a state name or an object of state values, or several active children of a non-parallel state), and values naming states the machine does not have. Unknown fields are still ignored.

    import { createActor, InvalidSnapshotError } from 'xstate';
    
    const actor = createActor(machine, { snapshot: stored });
    const snapshot = actor.getSnapshot();
    if (snapshot.status === 'error' && snapshot.error instanceof InvalidSnapshotError) {
      // fall back to a fresh actor
    }
  • 73b2edf: Fix several v6 alpha transition, typing, and inspection issues:

    • Preserve enqueued effects when transition functions wrap enq calls in try/catch, and avoid reevaluating ordinary effect-only transitions during selection.
    • Preserve declared schema context types in callbacks and snapshots, and reject patches containing only undeclared keys.
    • Infer invoke input mapper arguments when the registered actor accepts unknown or any input.
    • Report the sender of the event being processed in transition inspection events, even when more events are queued during processing.
    • Report inspection observer exceptions without interrupting actor processing or other inspection observers.
    • Include the source state, event, and original cause when graph transition evaluation fails. Supply representative payloads through the graph traversal events option when transition functions require them.
  • 05f1e0f: Ship version-matched XState v6 documentation with the xstate package. Start with README.md or docs/index.md after installation for v6 examples and migration guidance.

  • 8773a22: Require payload samples for known event types with required fields in getShortestPaths, getSimplePaths, and getAdjacencyMap. Use an events map to explore multiple payloads while retaining default payload-free events, invoke completions, errors, and delays:

    getShortestPaths(machine, {
      events: {
        'item.add': [{ item: { qty: 1 } }, { item: { qty: 0 } }]
      }
    });

    Each map entry also accepts a snapshot callback returning nonempty payload cases. Event arrays and callbacks returning events still replace defaults, but their types must cover every required payload event. Fixed-sequence replay with getPathsFromEvents requires only the supplied events. Coverage remains sample-based.

    Unconfigured wildcard descriptors retain their default samples alongside concrete event cases. Use an event array to restrict traversal to supplied concrete events.

@xstate/effect@1.0.0-alpha.9

Major Changes

  • ceeebb0: taggedState(...) tags a root parallel state with the machine id instead of '(machine)', or with '' when the machine has no id. TaggedState and StateTag type the tag the same way.

    const release = createMachine({ id: 'release', type: 'parallel', states: { review: {}, build: {} } });
    
    Match.type<TaggedState<typeof release>>().pipe(
      Match.tag('release', () => 'in progress'), // was Match.tag('(machine)', ...)
      Match.exhaustive
    );

@xstate/test@2.0.0-alpha.4

Major Changes

  • 5b6df81: @xstate/test/effect-schema now requires stable Effect 4 (effect@^4.0.0). fromEffectSchema() builds fast-check arbitraries from the schema's AST. It supports primitives, literals, enums, unions, arrays, tuples, structs with optional properties, records with string keys, and refinements. Unsupported nodes such as Schema.Date throw an error naming the node. Pass override to supply an arbitrary for them:

    import * as fc from 'fast-check';
    import * as Schema from 'effect/Schema';
    import { fromEffectSchema } from '@xstate/test/effect-schema';
    
    fromEffectSchema(Schema.Struct({ at: Schema.Date }), {
      override: (ast) =>
        ast._tag === 'Declaration' ? fc.date({ noInvalidDate: true }) : undefined
    });
  • 5b6df81: The @xstate/test entry point no longer exports the internal types PropertyExecutionConfig and PropertyTargetObservation.

    The vitest peer dependency now accepts Vitest 3 and Vitest 4.

@xstate/codemod@0.1.0-alpha.4

Minor Changes

  • 39d3b5c: Added the report-id-path-targets transform. It reports, without rewriting, #a.b targets and matches('#a.b') or stateIn('#a.b') arguments that are not whole state ids of the machine config that contains them (references outside a machine config are always reported), since v6 resolves # targets by exact id only.

    // Reported: `flow` is an explicit id, and `flow.review` is not an id
    on: { review: { target: '#flow.review' } }
    // Not reported: the full implicit id
    on: { review: { target: '#shop.wizard.review' } }

Patch Changes

  • ceeebb0: xstate-codemod migrate renames ActorRefFromLogic imports and usages to ActorRefFrom.

@xstate/react@7.0.0-alpha.6

Patch Changes

  • 5b6df81: xstate is now a required peer dependency of @xstate/react, @xstate/vue, @xstate/svelte, and @xstate/solid. Package managers now warn when xstate is missing instead of letting the adapter fail at runtime.

    useActorRef(), useActor(), and useMachine() in @xstate/react no longer write implementations provided on a later render onto the machine passed on the first render. A module-level machine shared by several components keeps its own implementations:

    const machine = createMachine({
      actions: { notify: () => {} },
      on: { DO: ({ actions }, enq) => enq(actions.notify) }
    });
    
    function Custom({ onNotify }) {
      // Only this component's actor uses `onNotify`.
      useActorRef(machine.provide({ actions: { notify: onNotify } }));
      return null;
    }
    
    function Plain() {
      // Still uses the original `notify`.
      useActorRef(machine);
      return null;
    }

@xstate/scxml@1.0.0-alpha.3

Patch Changes

  • 5b6df81: SCXML done.invoke.<id> and done.state.<id> transitions now match xstate.done.actor and xstate.done.state events by their actorId and stateId. Behavior is unchanged for SCXML documents.
  • ceeebb0: An SCXML document without a name creates a machine without an id (machine.id is '') instead of one named (machine), matching createMachine. The _name system variable is '' for such documents.

@xstate/solid@3.0.0-alpha.3

Patch Changes

  • 5b6df81: xstate is now a required peer dependency of @xstate/react, @xstate/vue, @xstate/svelte, and @xstate/solid. Package managers now warn when xstate is missing instead of letting the adapter fail at runtime.

    useActorRef(), useActor(), and useMachine() in @xstate/react no longer write implementations provided on a later render onto the machine passed on the first render. A module-level machine shared by several components keeps its own implementations:

    const machine = createMachine({
      actions: { notify: () => {} },
      on: { DO: ({ actions }, enq) => enq(actions.notify) }
    });
    
    function Custom({ onNotify }) {
      // Only this component's actor uses `onNotify`.
      useActorRef(machine.provide({ actions: { notify: onNotify } }));
      return null;
    }
    
    function Plain() {
      // Still uses the original `notify`.
      useActorRef(machine);
      return null;
    }

@xstate/svelte@6.0.0-alpha.4

Patch Changes

  • 5b6df81: xstate is now a required peer dependency of @xstate/react, @xstate/vue, @xstate/svelte, and @xstate/solid. Package managers now warn when xstate is missing instead of letting the adapter fail at runtime.

    useActorRef(), useActor(), and useMachine() in @xstate/react no longer write implementations provided on a later render onto the machine passed on the first render. A module-level machine shared by several components keeps its own implementations:

    const machine = createMachine({
      actions: { notify: () => {} },
      on: { DO: ({ actions }, enq) => enq(actions.notify) }
    });
    
    function Custom({ onNotify }) {
      // Only this component's actor uses `onNotify`.
      useActorRef(machine.provide({ actions: { notify: onNotify } }));
      return null;
    }
    
    function Plain() {
      // Still uses the original `notify`.
      useActorRef(machine);
      return null;
    }

@xstate/vue@6.0.0-alpha.4

Patch Changes

  • 5b6df81: xstate is now a required peer dependency of @xstate/react, @xstate/vue, @xstate/svelte, and @xstate/solid. Package managers now warn when xstate is missing instead of letting the adapter fail at runtime.

    useActorRef(), useActor(), and useMachine() in @xstate/react no longer write implementations provided on a later render onto the machine passed on the first render. A module-level machine shared by several components keeps its own implementations:

    const machine = createMachine({
      actions: { notify: () => {} },
      on: { DO: ({ actions }, enq) => enq(actions.notify) }
    });
    
    function Custom({ onNotify }) {
      // Only this component's actor uses `onNotify`.
      useActorRef(machine.provide({ actions: { notify: onNotify } }));
      return null;
    }
    
    function Plain() {
      // Still uses the original `notify`.
      useActorRef(machine);
      return null;
    }

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 9ad864a1-fbaa-40b3-a89e-627f3839b0b9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@github-actions
github-actions Bot force-pushed the changeset-release/next branch 4 times, most recently from 56bac38 to d6810a3 Compare October 19, 2026 20:49
@github-actions
github-actions Bot force-pushed the changeset-release/next branch from d6810a3 to 957b907 Compare October 19, 2026 21:29
@davidkpiano
davidkpiano merged commit c628b91 into next Oct 19, 2026
2 checks passed
@davidkpiano
davidkpiano deleted the changeset-release/next branch October 19, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant