1+ import isPlainObject from 'is-plain-obj'
12import { PATH , PROXY_TREE , VALUE } from 'proxy-state-tree'
2-
3- import { deepCopy } from './utils'
43import { IState } from '.'
54
65type TState = {
@@ -16,23 +15,48 @@ type TEvents = {
1615 data ?: any
1716}
1817
19-
20- export type StatemachineTransitions < States extends TState , Events extends TEvents , BaseState extends TBaseState > = {
21- [ Type in Events [ "type" ] ] : [ BaseState ] extends [ never ] ?
22- ( ( state : States , payload : Events extends { type : Type } ? Events [ "data" ] : never ) => States | void ) :
23- ( ( state : States & BaseState , payload : Events extends { type : Type } ? Events [ "data" ] : never ) => States | void )
18+ export type StatemachineTransitions <
19+ States extends TState ,
20+ Events extends TEvents ,
21+ BaseState extends TBaseState
22+ > = {
23+ [ Type in Events [ 'type' ] ] : [ BaseState ] extends [ never ]
24+ ? ( (
25+ state : States ,
26+ payload : Events extends { type : Type } ? Events [ 'data' ] : never
27+ ) => States | void )
28+ : ( (
29+ state : States & BaseState ,
30+ payload : Events extends { type : Type } ? Events [ 'data' ] : never
31+ ) => States | void )
2432}
2533
26- export interface MachineMethods < States extends TState , Events extends TEvents , BaseState extends TBaseState > {
27- matches < T extends States [ "current" ] > (
28- current : T ,
29- ) : Statemachine < States extends { current : T } ? States : never , Events , BaseState > | undefined
30- send < T extends Events [ "type" ] > (
31- ...args : Events extends { type : T , data : any } ? [ T , Events [ "data" ] ] : [ T ]
34+ export interface MachineMethods <
35+ States extends TState ,
36+ Events extends TEvents ,
37+ BaseState extends TBaseState
38+ > {
39+ matches < T extends States [ 'current' ] > (
40+ current : T
41+ ) :
42+ | Statemachine <
43+ States extends { current : T } ? States : never ,
44+ Events ,
45+ BaseState
46+ >
47+ | undefined
48+ send < T extends Events [ 'type' ] > (
49+ ...args : Events extends { type : T ; data : any } ? [ T , Events [ 'data' ] ] : [ T ]
3250 ) : Statemachine < States , Events , BaseState >
3351}
3452
35- export type Statemachine < States extends TState , Events extends TEvents , BaseState extends TBaseState = never > = [ BaseState ] extends [ never ] ? States & MachineMethods < States , Events , BaseState > : States & BaseState & MachineMethods < States , Events , BaseState >
53+ export type Statemachine <
54+ States extends TState ,
55+ Events extends TEvents ,
56+ BaseState extends TBaseState = never
57+ > = [ BaseState ] extends [ never ]
58+ ? States & MachineMethods < States , Events , BaseState >
59+ : States & BaseState & MachineMethods < States , Events , BaseState >
3660
3761const INITIAL_STATE = Symbol ( 'INITIAL_STATE' )
3862const TRANSITIONS = Symbol ( 'TRANSITIONS' )
@@ -41,15 +65,52 @@ const IS_DISPOSED = Symbol('IS_DISPOSED')
4165const CURRENT_KEYS = Symbol ( 'CURRENT_KEYS' )
4266const BASE_STATE = Symbol ( 'BASE_STATE' )
4367
44- export class StateMachine < State extends TState , Events extends TEvents , BaseState extends TBaseState > {
45- current : State [ "current" ]
46- private [ INITIAL_STATE ] : State [ "current" ]
68+ // We have to export here to avoid a circular dependency issue with "utils"
69+ export function deepCopy ( obj ) {
70+ if ( obj instanceof StateMachine ) {
71+ return ( obj as any ) . clone ( )
72+ } else if ( isPlainObject ( obj ) ) {
73+ return Object . keys ( obj ) . reduce ( ( aggr : any , key ) => {
74+ if ( key === '__esModule' ) {
75+ return aggr
76+ }
77+
78+ const originalDescriptor = Object . getOwnPropertyDescriptor ( obj , key )
79+ const isAGetter = originalDescriptor && 'get' in originalDescriptor
80+ const value = obj [ key ]
81+
82+ if ( isAGetter ) {
83+ Object . defineProperty ( aggr , key , originalDescriptor as any )
84+ } else {
85+ aggr [ key ] = deepCopy ( value )
86+ }
87+
88+ return aggr
89+ } , { } )
90+ } else if ( Array . isArray ( obj ) ) {
91+ return obj . map ( ( item ) => deepCopy ( item ) )
92+ }
93+
94+ return obj
95+ }
96+
97+ export class StateMachine <
98+ State extends TState ,
99+ Events extends TEvents ,
100+ BaseState extends TBaseState
101+ > {
102+ current : State [ 'current' ]
103+ private [ INITIAL_STATE ] : State [ 'current' ]
47104 private [ TRANSITIONS ] : StatemachineTransitions < State , Events , BaseState >
48105 private [ STATE ] : any
49106 private [ BASE_STATE ] : BaseState
50107 private [ IS_DISPOSED ] = false
51108 private clone ( ) {
52- return new StateMachine ( this [ TRANSITIONS ] , deepCopy ( this [ STATE ] ) , deepCopy ( this [ BASE_STATE ] ) )
109+ return new StateMachine (
110+ this [ TRANSITIONS ] ,
111+ deepCopy ( this [ STATE ] ) ,
112+ deepCopy ( this [ BASE_STATE ] )
113+ )
53114 }
54115 private dispose ( ) {
55116 Object . keys ( this [ VALUE ] ) . forEach ( ( key ) => {
@@ -59,7 +120,11 @@ export class StateMachine<State extends TState, Events extends TEvents, BaseStat
59120 } )
60121 this [ VALUE ] [ IS_DISPOSED ] = true
61122 }
62- constructor ( transitions : StatemachineTransitions < State , Events , BaseState > , state : State , baseState : BaseState ) {
123+ constructor (
124+ transitions : StatemachineTransitions < State , Events , BaseState > ,
125+ state : State ,
126+ baseState : BaseState
127+ ) {
63128 this [ STATE ] = state
64129 this [ BASE_STATE ] = baseState
65130 this [ INITIAL_STATE ] = state . current
@@ -71,12 +136,16 @@ export class StateMachine<State extends TState, Events extends TEvents, BaseStat
71136 send ( type , data ) {
72137 if ( this [ VALUE ] [ IS_DISPOSED ] ) {
73138 if ( process . env . NODE_ENV === 'development' ) {
74- console . warn ( `Overmind - The statemachine at "${ this [ PATH ] } " has been disposed, but you tried to transition on it` )
139+ console . warn (
140+ `Overmind - The statemachine at "${
141+ this [ PATH ]
142+ } " has been disposed, but you tried to transition on it`
143+ )
75144 }
76145 return this
77146 }
78147
79- const tree = ( this [ PROXY_TREE ] . master . mutationTree || this [ PROXY_TREE ] )
148+ const tree = this [ PROXY_TREE ] . master . mutationTree || this [ PROXY_TREE ]
80149 const transition = this [ VALUE ] [ TRANSITIONS ] [ type ]
81150
82151 tree . enableMutations ( )
@@ -103,16 +172,31 @@ export class StateMachine<State extends TState, Events extends TEvents, BaseStat
103172 }
104173}
105174
106- export type StatemachineFactory < States extends TState , Events extends TEvents , BaseState extends TBaseState > = [ BaseState ] extends [ never ] ? {
107- create ( state : States ) : Statemachine < States , Events , { } >
108- } : {
109- create ( state : States , baseState : BaseState ) : Statemachine < States , Events , BaseState >
110- }
175+ export type StatemachineFactory <
176+ States extends TState ,
177+ Events extends TEvents ,
178+ BaseState extends TBaseState
179+ > = [ BaseState ] extends [ never ]
180+ ? {
181+ create ( state : States ) : Statemachine < States , Events , { } >
182+ }
183+ : {
184+ create (
185+ state : States ,
186+ baseState : BaseState
187+ ) : Statemachine < States , Events , BaseState >
188+ }
111189
112- export function statemachine < States extends TState , Events extends TEvents , BaseState extends TBaseState = never > ( transitions : StatemachineTransitions < States , Events , BaseState > ) : StatemachineFactory < States , Events , BaseState > {
113- return {
114- create ( state , baseState ) {
190+ export function statemachine <
191+ States extends TState ,
192+ Events extends TEvents ,
193+ BaseState extends TBaseState = never
194+ > (
195+ transitions : StatemachineTransitions < States , Events , BaseState >
196+ ) : StatemachineFactory < States , Events , BaseState > {
197+ return {
198+ create ( state , baseState ) {
115199 return new StateMachine ( transitions , state as any , baseState as any )
116- }
117- } as any
200+ } ,
201+ } as any
118202}
0 commit comments