Skip to content

Commit

Permalink
Add support for the typegen in @xstate/svelte (#3254)
Browse files Browse the repository at this point in the history
* Add support for the typegen in `@xstate/svelte`

* Refactor `@xstate/svelte/fsm` to use `TMachine`

* Fixed the return type of FSM's useMachine in Svelte
  • Loading branch information
Andarist authored Apr 27, 2022
1 parent 390a115 commit c0b787d
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 43 deletions.
7 changes: 7 additions & 0 deletions .changeset/lucky-tables-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@xstate/svelte': major
---

The major version of this package had to be bumped to allow integrating with the typegen. This package will now require TS version 4.0 or greater.

When using hooks from `@xstate/svelte` it's recommended to skip providing explicit generics to them. Note that that generics list has changed since v1 and we now only accept a single generic, `TMachine`.
39 changes: 15 additions & 24 deletions packages/xstate-svelte/src/fsm.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
import { onDestroy } from 'svelte';
import { readable } from 'svelte/store';
import {
createMachine,
interpret,
EventObject,
StateMachine,
Typestate
MachineImplementationsFrom,
ServiceFrom,
StateFrom,
StateMachine
} from '@xstate/fsm';
import { onDestroy } from 'svelte';
import { Readable, readable } from 'svelte/store';

interface UseMachineOptions<
TContext extends object,
TEvent extends EventObject
> {
/**
* If provided, will replace machine's `actions`.
*/
actions: StateMachine.ActionMap<TContext, TEvent>;
}

export function useMachine<
TContext extends object,
TEvent extends EventObject,
TTypestate extends Typestate<TContext>
>(
machine: StateMachine.Machine<TContext, TEvent, TTypestate>,
options: Partial<UseMachineOptions<TContext, TEvent>> = {}
) {
export function useMachine<TMachine extends StateMachine.AnyMachine>(
machine: TMachine,
options?: MachineImplementationsFrom<TMachine>
): {
state: Readable<StateFrom<TMachine>>;
send: ServiceFrom<TMachine>['send'];
service: ServiceFrom<TMachine>;
} {
const resolvedMachine = createMachine(
machine.config,
options ? options : (machine as any)._options
Expand All @@ -43,5 +34,5 @@ export function useMachine<
}).unsubscribe;
});

return { state, send: service.send, service };
return { state, send: service.send, service } as any;
}
69 changes: 50 additions & 19 deletions packages/xstate-svelte/src/useMachine.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,72 @@
import { onDestroy } from 'svelte';
import { readable } from 'svelte/store';
import { Readable, readable } from 'svelte/store';
import {
interpret,
AnyStateMachine,
AreAllImplementationsAssumedToBeProvided,
EventObject,
StateMachine,
State,
InternalMachineOptions,
interpret,
InterpreterFrom,
InterpreterOptions,
MachineOptions,
State,
StateConfig,
Typestate
StateFrom
} from 'xstate';

type Prop<T, K> = K extends keyof T ? T[K] : never;
interface UseMachineOptions<
TContext extends object,
TEvent extends EventObject
> {
/**
* If provided, will be merged with machine's `context`.
*/
context: Partial<TContext>;
context?: Partial<TContext>;
/**
* The state to rehydrate the machine to. The machine will
* start at this state instead of its `initialState`.
*/
state: StateConfig<TContext, TEvent>;
state?: StateConfig<TContext, TEvent>;
}

export function useMachine<
TContext extends object,
TEvent extends EventObject,
TTypestate extends Typestate<TContext>
>(
machine: StateMachine<TContext, any, TEvent, TTypestate>,
options: Partial<InterpreterOptions> &
Partial<UseMachineOptions<TContext, TEvent>> &
Partial<MachineOptions<TContext, TEvent>> = {}
) {
type RestParams<
TMachine extends AnyStateMachine
> = AreAllImplementationsAssumedToBeProvided<
TMachine['__TResolvedTypesMeta']
> extends false
? [
options: InterpreterOptions &
UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> &
InternalMachineOptions<
TMachine['__TContext'],
TMachine['__TEvent'],
TMachine['__TResolvedTypesMeta'],
true
>
]
: [
options?: InterpreterOptions &
UseMachineOptions<TMachine['__TContext'], TMachine['__TEvent']> &
InternalMachineOptions<
TMachine['__TContext'],
TMachine['__TEvent'],
TMachine['__TResolvedTypesMeta']
>
];

type UseMachineReturn<
TMachine extends AnyStateMachine,
TInterpreter = InterpreterFrom<TMachine>
> = {
state: Readable<StateFrom<TMachine>>;
send: Prop<TInterpreter, 'send'>;
service: TInterpreter;
};

export function useMachine<TMachine extends AnyStateMachine>(
machine: TMachine,
...[options = {}]: RestParams<TMachine>
): UseMachineReturn<TMachine> {
const {
context,
guards,
Expand Down Expand Up @@ -75,5 +106,5 @@ export function useMachine<
}).unsubscribe;
});

return { state, send: service.send, service };
return { state, send: service.send, service } as any;
}

0 comments on commit c0b787d

Please sign in to comment.