xstate 4.20.2 → 4.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/es/types.d.ts CHANGED
@@ -152,7 +152,7 @@ export interface InvokeMeta {
152
152
  * @param context The current machine `context`
153
153
  * @param event The event that invoked the service
154
154
  */
155
- export declare type InvokeCreator<TContext, TEvent extends EventObject, TFinalContext = any> = (context: TContext, event: TEvent, meta: InvokeMeta) => PromiseLike<TFinalContext> | StateMachine<TFinalContext, any, any> | Subscribable<EventObject> | InvokeCallback<any, TEvent>;
155
+ export declare type InvokeCreator<TContext, TEvent extends EventObject, TFinalContext = any> = (context: TContext, event: TEvent, meta: InvokeMeta) => PromiseLike<TFinalContext> | StateMachine<TFinalContext, any, any> | Subscribable<EventObject> | InvokeCallback<any, TEvent> | Behavior<any>;
156
156
  export interface InvokeDefinition<TContext, TEvent extends EventObject> extends ActivityDefinition<TContext, TEvent> {
157
157
  /**
158
158
  * The source of the machine to be invoked, or the machine itself.
@@ -878,7 +878,7 @@ export interface Subscribable<T> {
878
878
  subscribe(observer: Observer<T>): Subscription;
879
879
  subscribe(next: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;
880
880
  }
881
- export declare type Spawnable = StateMachine<any, any, any> | Promise<any> | InvokeCallback | Subscribable<any>;
881
+ export declare type Spawnable = StateMachine<any, any, any> | PromiseLike<any> | InvokeCallback | Subscribable<any> | Behavior<any>;
882
882
  export declare type ExtractEvent<TEvent extends EventObject, TEventType extends TEvent['type']> = TEvent extends {
883
883
  type: TEventType;
884
884
  } ? TEvent : never;
@@ -896,13 +896,24 @@ export interface ActorRef<TEvent extends EventObject, TEmitted = any> extends Su
896
896
  * @deprecated Use `ActorRef` instead.
897
897
  */
898
898
  export declare type SpawnedActorRef<TEvent extends EventObject, TEmitted = any> = ActorRef<TEvent, TEmitted>;
899
- export declare type ActorRefFrom<T extends StateMachine<any, any, any> | Promise<any>> = T extends StateMachine<infer TContext, any, infer TEvent, infer TTypestate> ? ActorRef<TEvent, State<TContext, TEvent, any, TTypestate>> & {
899
+ export declare type ActorRefFrom<T extends StateMachine<any, any, any> | Promise<any> | Behavior<any>> = T extends StateMachine<infer TContext, any, infer TEvent, infer TTypestate> ? ActorRef<TEvent, State<TContext, TEvent, any, TTypestate>> & {
900
900
  /**
901
901
  * @deprecated Use `.getSnapshot()` instead.
902
902
  */
903
903
  state: State<TContext, TEvent, any, TTypestate>;
904
- } : T extends Promise<infer U> ? ActorRef<never, U> : never;
904
+ } : T extends Promise<infer U> ? ActorRef<never, U> : T extends Behavior<infer TEvent, infer TEmitted> ? ActorRef<TEvent, TEmitted> : never;
905
905
  export declare type AnyInterpreter = Interpreter<any, any, any, any>;
906
906
  export declare type InterpreterFrom<T extends StateMachine<any, any, any, any>> = T extends StateMachine<infer TContext, infer TStateSchema, infer TEvent, infer TTypestate> ? Interpreter<TContext, TStateSchema, TEvent, TTypestate> : never;
907
+ export interface ActorContext<TEvent extends EventObject, TEmitted> {
908
+ parent?: ActorRef<any, any>;
909
+ self: ActorRef<TEvent, TEmitted>;
910
+ id: string;
911
+ observers: Set<Observer<TEmitted>>;
912
+ }
913
+ export interface Behavior<TEvent extends EventObject, TEmitted = any> {
914
+ transition: (state: TEmitted, event: TEvent, actorCtx: ActorContext<TEvent, TEmitted>) => TEmitted;
915
+ initialState: TEmitted;
916
+ start?: (actorCtx: ActorContext<TEvent, TEmitted>) => TEmitted;
917
+ }
907
918
  export {};
908
919
  //# sourceMappingURL=types.d.ts.map
package/es/utils.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Event, StateValue, ActionType, Action, EventObject, PropertyMapper, Mapper, EventType, HistoryValue, AssignAction, Condition, Subscribable, StateMachine, ConditionPredicate, SCXML, StateLike, EventData, TransitionConfig, TransitionConfigTarget, NullEvent, SingleOrArray, Guard, InvokeSourceDefinition } from './types';
1
+ import { Event, StateValue, ActionType, Action, EventObject, PropertyMapper, Mapper, EventType, HistoryValue, AssignAction, Condition, Subscribable, StateMachine, ConditionPredicate, SCXML, StateLike, EventData, TransitionConfig, TransitionConfigTarget, NullEvent, SingleOrArray, Guard, InvokeSourceDefinition, Observer, Behavior } from './types';
2
2
  import { StateNode } from './StateNode';
3
- import { Observer, State } from '.';
3
+ import { State } from './State';
4
4
  import { Actor } from './Actor';
5
5
  export declare function keys<T extends object>(value: T): Array<keyof T & string>;
6
6
  export declare function matchesState(parentStateId: StateValue, childStateId: StateValue, delimiter?: string): boolean;
@@ -40,6 +40,7 @@ export declare function toArray<T>(value: T[] | T | undefined): T[];
40
40
  export declare function mapContext<TContext, TEvent extends EventObject>(mapper: Mapper<TContext, TEvent, any> | PropertyMapper<TContext, TEvent, any>, context: TContext, _event: SCXML.Event<TEvent>): any;
41
41
  export declare function isBuiltInEvent(eventType: EventType): boolean;
42
42
  export declare function isPromiseLike(value: any): value is PromiseLike<any>;
43
+ export declare function isBehavior(value: any): value is Behavior<any, any>;
43
44
  export declare function partition<T, A extends T, B extends T>(items: T[], predicate: (item: T) => item is A): [A[], B[]];
44
45
  export declare function updateHistoryStates(hist: HistoryValue, stateValue: StateValue): Record<string, HistoryValue | undefined>;
45
46
  export declare function updateHistoryValue(hist: HistoryValue, stateValue: StateValue): HistoryValue;
package/es/utils.js CHANGED
@@ -301,6 +301,10 @@ function isPromiseLike(value) {
301
301
  return false;
302
302
  }
303
303
 
304
+ function isBehavior(value) {
305
+ return value !== null && typeof value === 'object' && 'transition' in value && typeof value.transition === 'function';
306
+ }
307
+
304
308
  function partition(items, predicate) {
305
309
  var e_6, _a;
306
310
 
@@ -617,4 +621,4 @@ function toObserver(nextHandler, errorHandler, completionHandler) {
617
621
  };
618
622
  }
619
623
 
620
- export { evaluateGuard, flatten, getEventType, isActor, isArray, isBuiltInEvent, isFunction, isMachine, isObservable, isPromiseLike, isStateLike, isString, keys, mapContext, mapFilterValues, mapValues, matchesState, nestedPath, normalizeTarget, partition, path, pathToStateValue, reportUnhandledExceptionOnInvocation, symbolObservable, toArray, toArrayStrict, toEventObject, toGuard, toInvokeSource, toObserver, toSCXMLEvent, toStatePath, toStatePaths, toStateValue, toTransitionConfigArray, uniqueId, updateContext, updateHistoryStates, updateHistoryValue, warn };
624
+ export { evaluateGuard, flatten, getEventType, isActor, isArray, isBehavior, isBuiltInEvent, isFunction, isMachine, isObservable, isPromiseLike, isStateLike, isString, keys, mapContext, mapFilterValues, mapValues, matchesState, nestedPath, normalizeTarget, partition, path, pathToStateValue, reportUnhandledExceptionOnInvocation, symbolObservable, toArray, toArrayStrict, toEventObject, toGuard, toInvokeSource, toObserver, toSCXMLEvent, toStatePath, toStatePaths, toStateValue, toTransitionConfigArray, uniqueId, updateContext, updateHistoryStates, updateHistoryValue, warn };
package/lib/Machine.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import { StateMachine, MachineOptions, DefaultContext, MachineConfig, StateSchema, EventObject, AnyEventObject, Typestate } from './types';
2
2
  import { Model, ModelContextFrom, ModelEventsFrom } from './model';
3
+ /**
4
+ * @deprecated Use `createMachine(...)` instead.
5
+ */
3
6
  export declare function Machine<TContext = any, TEvent extends EventObject = AnyEventObject>(config: MachineConfig<TContext, any, TEvent>, options?: Partial<MachineOptions<TContext, TEvent>>, initialContext?: TContext): StateMachine<TContext, any, TEvent>;
4
7
  export declare function Machine<TContext = DefaultContext, TStateSchema extends StateSchema = any, TEvent extends EventObject = AnyEventObject>(config: MachineConfig<TContext, TStateSchema, TEvent>, options?: Partial<MachineOptions<TContext, TEvent>>, initialContext?: TContext): StateMachine<TContext, TStateSchema, TEvent>;
5
8
  export declare function createMachine<TModel extends Model<any, any, any>, TContext = ModelContextFrom<TModel>, TEvent extends EventObject = ModelEventsFrom<TModel>, TTypestate extends Typestate<TContext> = {
package/lib/Machine.js CHANGED
@@ -4,16 +4,10 @@ exports.createMachine = exports.Machine = void 0;
4
4
  var StateNode_1 = require("./StateNode");
5
5
  function Machine(config, options, initialContext) {
6
6
  if (initialContext === void 0) { initialContext = config.context; }
7
- var resolvedInitialContext = typeof initialContext === 'function'
8
- ? initialContext()
9
- : initialContext;
10
- return new StateNode_1.StateNode(config, options, resolvedInitialContext);
7
+ return new StateNode_1.StateNode(config, options, initialContext);
11
8
  }
12
9
  exports.Machine = Machine;
13
10
  function createMachine(config, options) {
14
- var resolvedInitialContext = typeof config.context === 'function'
15
- ? config.context()
16
- : config.context;
17
- return new StateNode_1.StateNode(config, options, resolvedInitialContext);
11
+ return new StateNode_1.StateNode(config, options);
18
12
  }
19
13
  exports.createMachine = createMachine;
@@ -11,7 +11,7 @@ declare class StateNode<TContext = any, TStateSchema extends StateSchema = any,
11
11
  /**
12
12
  * The initial extended state
13
13
  */
14
- context: Readonly<TContext>;
14
+ private _context;
15
15
  /**
16
16
  * The relative key of the state node, which represents its location in the overall state value.
17
17
  */
@@ -122,7 +122,7 @@ declare class StateNode<TContext = any, TStateSchema extends StateSchema = any,
122
122
  /**
123
123
  * The initial extended state
124
124
  */
125
- context?: Readonly<TContext>);
125
+ _context?: Readonly<TContext> | (() => Readonly<TContext>));
126
126
  private _init;
127
127
  /**
128
128
  * Clones this state machine with custom options and context.
@@ -130,13 +130,14 @@ declare class StateNode<TContext = any, TStateSchema extends StateSchema = any,
130
130
  * @param options Options (actions, guards, activities, services) to recursively merge with the existing options.
131
131
  * @param context Custom context (will override predefined context)
132
132
  */
133
- withConfig(options: Partial<MachineOptions<TContext, TEvent>>, context?: TContext | undefined): StateNode<TContext, TStateSchema, TEvent, TTypestate>;
133
+ withConfig(options: Partial<MachineOptions<TContext, TEvent>>, context?: TContext): StateNode<TContext, TStateSchema, TEvent, TTypestate>;
134
134
  /**
135
135
  * Clones this state machine with custom context.
136
136
  *
137
137
  * @param context Custom context (will override predefined context, not recursive)
138
138
  */
139
139
  withContext(context: TContext): StateNode<TContext, TStateSchema, TEvent, TTypestate>;
140
+ get context(): TContext;
140
141
  /**
141
142
  * The well-structured state node definition.
142
143
  */
package/lib/StateNode.js CHANGED
@@ -99,13 +99,13 @@ var StateNode = /** @class */ (function () {
99
99
  /**
100
100
  * The initial extended state
101
101
  */
102
- context // TODO: this is unsafe, but we're removing it in v5 anyway
102
+ _context // TODO: this is unsafe, but we're removing it in v5 anyway
103
103
  ) {
104
104
  var _this = this;
105
- if (context === void 0) { context = undefined; }
105
+ if (_context === void 0) { _context = config.context; }
106
106
  var _a;
107
107
  this.config = config;
108
- this.context = context;
108
+ this._context = _context;
109
109
  /**
110
110
  * The order this state node appears. Corresponds to the implicit SCXML document order.
111
111
  */
@@ -255,7 +255,6 @@ var StateNode = /** @class */ (function () {
255
255
  * @param context Custom context (will override predefined context)
256
256
  */
257
257
  StateNode.prototype.withConfig = function (options, context) {
258
- if (context === void 0) { context = this.context; }
259
258
  var _a = this.options, actions = _a.actions, activities = _a.activities, guards = _a.guards, services = _a.services, delays = _a.delays;
260
259
  return new StateNode(this.config, {
261
260
  actions: __assign(__assign({}, actions), options.actions),
@@ -263,7 +262,7 @@ var StateNode = /** @class */ (function () {
263
262
  guards: __assign(__assign({}, guards), options.guards),
264
263
  services: __assign(__assign({}, services), options.services),
265
264
  delays: __assign(__assign({}, delays), options.delays)
266
- }, context);
265
+ }, context !== null && context !== void 0 ? context : this.context);
267
266
  };
268
267
  /**
269
268
  * Clones this state machine with custom context.
@@ -273,6 +272,13 @@ var StateNode = /** @class */ (function () {
273
272
  StateNode.prototype.withContext = function (context) {
274
273
  return new StateNode(this.config, this.options, context);
275
274
  };
275
+ Object.defineProperty(StateNode.prototype, "context", {
276
+ get: function () {
277
+ return utils_1.isFunction(this._context) ? this._context() : this._context;
278
+ },
279
+ enumerable: false,
280
+ configurable: true
281
+ });
276
282
  Object.defineProperty(StateNode.prototype, "definition", {
277
283
  /**
278
284
  * The well-structured state node definition.
@@ -716,7 +722,7 @@ var StateNode = /** @class */ (function () {
716
722
  var resolvedStateValue = utils_1.isString(state)
717
723
  ? this.resolve(utils_1.pathToStateValue(this.getResolvedPath(state)))
718
724
  : this.resolve(state);
719
- var resolvedContext = context ? context : this.machine.context;
725
+ var resolvedContext = context !== null && context !== void 0 ? context : this.machine.context;
720
726
  currentState = this.resolveState(State_1.State.from(resolvedStateValue, resolvedContext));
721
727
  }
722
728
  if (!environment_1.IS_PRODUCTION && _event.name === WILDCARD) {
@@ -0,0 +1,37 @@
1
+ import { ActorContext, ActorRef, Behavior, EventObject } from '.';
2
+ /**
3
+ * Returns an actor behavior from a reducer and its initial state.
4
+ *
5
+ * @param transition The pure reducer that returns the next state given the current state and event.
6
+ * @param initialState The initial state of the reducer.
7
+ * @returns An actor behavior
8
+ */
9
+ export declare function fromReducer<TState, TEvent extends EventObject>(transition: (state: TState, event: TEvent, actorContext: ActorContext<TEvent, TState>) => TState, initialState: TState): Behavior<TEvent, TState>;
10
+ declare type PromiseEvents<T> = {
11
+ type: 'fulfill';
12
+ data: T;
13
+ } | {
14
+ type: 'reject';
15
+ error: unknown;
16
+ };
17
+ declare type PromiseState<T> = {
18
+ status: 'pending';
19
+ data: undefined;
20
+ error: undefined;
21
+ } | {
22
+ status: 'fulfilled';
23
+ data: T;
24
+ error: undefined;
25
+ } | {
26
+ status: 'rejected';
27
+ data: undefined;
28
+ error: any;
29
+ };
30
+ export declare function fromPromise<T>(promiseFn: () => Promise<T>): Behavior<PromiseEvents<T>, PromiseState<T>>;
31
+ interface SpawnBehaviorOptions {
32
+ id?: string;
33
+ parent?: ActorRef<any>;
34
+ }
35
+ export declare function spawnBehavior<TEvent extends EventObject, TEmitted>(behavior: Behavior<TEvent, TEmitted>, options?: SpawnBehaviorOptions): ActorRef<TEvent, TEmitted>;
36
+ export {};
37
+ //# sourceMappingURL=behaviors.d.ts.map
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.spawnBehavior = exports.fromPromise = exports.fromReducer = void 0;
4
+ var actions_1 = require("./actions");
5
+ var Actor_1 = require("./Actor");
6
+ var utils_1 = require("./utils");
7
+ /**
8
+ * Returns an actor behavior from a reducer and its initial state.
9
+ *
10
+ * @param transition The pure reducer that returns the next state given the current state and event.
11
+ * @param initialState The initial state of the reducer.
12
+ * @returns An actor behavior
13
+ */
14
+ function fromReducer(transition, initialState) {
15
+ return {
16
+ transition: transition,
17
+ initialState: initialState
18
+ };
19
+ }
20
+ exports.fromReducer = fromReducer;
21
+ function fromPromise(promiseFn) {
22
+ var initialState = {
23
+ error: undefined,
24
+ data: undefined,
25
+ status: 'pending'
26
+ };
27
+ return {
28
+ transition: function (state, event, _a) {
29
+ var parent = _a.parent, id = _a.id, observers = _a.observers;
30
+ switch (event.type) {
31
+ case 'fulfill':
32
+ parent === null || parent === void 0 ? void 0 : parent.send(actions_1.doneInvoke(id, event.data));
33
+ return {
34
+ error: undefined,
35
+ data: event.data,
36
+ status: 'fulfilled'
37
+ };
38
+ case 'reject':
39
+ parent === null || parent === void 0 ? void 0 : parent.send(actions_1.error(id, event.error));
40
+ observers.forEach(function (observer) {
41
+ observer.error(event.error);
42
+ });
43
+ return {
44
+ error: event.error,
45
+ data: undefined,
46
+ status: 'rejected'
47
+ };
48
+ default:
49
+ return state;
50
+ }
51
+ },
52
+ initialState: initialState,
53
+ start: function (_a) {
54
+ var self = _a.self;
55
+ promiseFn().then(function (data) {
56
+ self.send({ type: 'fulfill', data: data });
57
+ }, function (reason) {
58
+ self.send({ type: 'reject', error: reason });
59
+ });
60
+ return initialState;
61
+ }
62
+ };
63
+ }
64
+ exports.fromPromise = fromPromise;
65
+ function spawnBehavior(behavior, options) {
66
+ if (options === void 0) { options = {}; }
67
+ var state = behavior.initialState;
68
+ var observers = new Set();
69
+ var mailbox = [];
70
+ var flushing = false;
71
+ var flush = function () {
72
+ if (flushing) {
73
+ return;
74
+ }
75
+ flushing = true;
76
+ while (mailbox.length > 0) {
77
+ var event_1 = mailbox.shift();
78
+ state = behavior.transition(state, event_1, actorCtx);
79
+ observers.forEach(function (observer) { return observer.next(state); });
80
+ }
81
+ flushing = false;
82
+ };
83
+ var actor = Actor_1.toActorRef({
84
+ id: options.id,
85
+ send: function (event) {
86
+ mailbox.push(event);
87
+ flush();
88
+ },
89
+ getSnapshot: function () { return state; },
90
+ subscribe: function (next, handleError, complete) {
91
+ var observer = utils_1.toObserver(next, handleError, complete);
92
+ observers.add(observer);
93
+ observer.next(state);
94
+ return {
95
+ unsubscribe: function () {
96
+ observers.delete(observer);
97
+ }
98
+ };
99
+ }
100
+ });
101
+ var actorCtx = {
102
+ parent: options.parent,
103
+ self: actor,
104
+ id: options.id || 'anonymous',
105
+ observers: observers
106
+ };
107
+ state = behavior.start ? behavior.start(actorCtx) : state;
108
+ return actor;
109
+ }
110
+ exports.spawnBehavior = spawnBehavior;
@@ -1,6 +1,5 @@
1
- import { StateMachine, Event, EventObject, DefaultContext, StateSchema, StateValue, InterpreterOptions, SingleOrArray, DoneEvent, MachineOptions, SCXML, EventData, Observer, Spawnable, Typestate } from './types';
1
+ import { StateMachine, Event, EventObject, DefaultContext, StateSchema, StateValue, InterpreterOptions, SingleOrArray, DoneEvent, MachineOptions, SCXML, EventData, Observer, Spawnable, Typestate, ActorRef, ActorRefFrom, Behavior, Subscription } from './types';
2
2
  import { State } from './State';
3
- import { ActorRef, ActorRefFrom, Subscription } from '.';
4
3
  export declare type StateListener<TContext, TEvent extends EventObject, TStateSchema extends StateSchema<TContext> = any, TTypestate extends Typestate<TContext> = {
5
4
  value: any;
6
5
  context: TContext;
@@ -171,6 +170,7 @@ export declare class Interpreter<TContext, TStateSchema extends StateSchema = an
171
170
  autoForward?: boolean;
172
171
  sync?: boolean;
173
172
  }): ActorRef<TChildEvent, State<TChildContext, TChildEvent>>;
173
+ private spawnBehavior;
174
174
  private spawnPromise;
175
175
  private spawnCallback;
176
176
  private spawnObservable;
@@ -183,6 +183,7 @@ export declare class Interpreter<TContext, TStateSchema extends StateSchema = an
183
183
  };
184
184
  getSnapshot(): State<TContext, TEvent, TStateSchema, TTypestate>;
185
185
  }
186
+ export declare function spawn<T extends Behavior<any, any>>(entity: T, nameOrOptions?: string | SpawnOptions): ActorRefFrom<T>;
186
187
  export declare function spawn<TC, TE extends EventObject>(entity: StateMachine<TC, any, TE>, nameOrOptions?: string | SpawnOptions): ActorRefFrom<StateMachine<TC, any, TE>>;
187
188
  export declare function spawn(entity: Spawnable, nameOrOptions?: string | SpawnOptions): ActorRef<any>;
188
189
  /**
@@ -56,6 +56,7 @@ var stateUtils_1 = require("./stateUtils");
56
56
  var registry_1 = require("./registry");
57
57
  var devTools_1 = require("./devTools");
58
58
  var serviceScope = require("./serviceScope");
59
+ var behaviors_1 = require("./behaviors");
59
60
  var DEFAULT_SPAWN_OPTIONS = { sync: false, autoForward: false };
60
61
  var InterpreterStatus;
61
62
  (function (InterpreterStatus) {
@@ -725,31 +726,28 @@ var Interpreter = /** @class */ (function () {
725
726
  var resolvedData = data
726
727
  ? utils_1.mapContext(data, context, _event)
727
728
  : undefined;
729
+ if (typeof serviceCreator === 'string') {
730
+ // TODO: warn
731
+ return;
732
+ }
728
733
  var source = utils_1.isFunction(serviceCreator)
729
734
  ? serviceCreator(context, _event.data, {
730
735
  data: resolvedData,
731
736
  src: invokeSource
732
737
  })
733
738
  : serviceCreator;
734
- if (utils_1.isPromiseLike(source)) {
735
- this.spawnPromise(Promise.resolve(source), id);
736
- }
737
- else if (utils_1.isFunction(source)) {
738
- this.spawnCallback(source, id);
739
- }
740
- else if (utils_1.isObservable(source)) {
741
- this.spawnObservable(source, id);
739
+ if (!source) {
740
+ // TODO: warn?
741
+ return;
742
742
  }
743
- else if (utils_1.isMachine(source)) {
744
- // TODO: try/catch here
745
- this.spawnMachine(resolvedData ? source.withContext(resolvedData) : source, {
746
- id: id,
743
+ var options = void 0;
744
+ if (utils_1.isMachine(source)) {
745
+ source = resolvedData ? source.withContext(resolvedData) : source;
746
+ options = {
747
747
  autoForward: autoForward
748
- });
749
- }
750
- else {
751
- // service is string
748
+ };
752
749
  }
750
+ this.spawn(source, id, options);
753
751
  }
754
752
  else {
755
753
  this.spawnActivity(activity);
@@ -808,6 +806,9 @@ var Interpreter = /** @class */ (function () {
808
806
  else if (utils_1.isMachine(entity)) {
809
807
  return this.spawnMachine(entity, __assign(__assign({}, options), { id: name }));
810
808
  }
809
+ else if (utils_1.isBehavior(entity)) {
810
+ return this.spawnBehavior(entity, name);
811
+ }
811
812
  else {
812
813
  throw new Error("Unable to spawn entity \"" + name + "\" of type \"" + typeof entity + "\".");
813
814
  }
@@ -838,10 +839,15 @@ var Interpreter = /** @class */ (function () {
838
839
  .start();
839
840
  return actor;
840
841
  };
842
+ Interpreter.prototype.spawnBehavior = function (behavior, id) {
843
+ var actorRef = behaviors_1.spawnBehavior(behavior, { id: id, parent: this });
844
+ this.children.set(id, actorRef);
845
+ return actorRef;
846
+ };
841
847
  Interpreter.prototype.spawnPromise = function (promise, id) {
842
848
  var _this = this;
843
849
  var canceled = false;
844
- var resolvedData = undefined;
850
+ var resolvedData;
845
851
  promise.then(function (response) {
846
852
  if (!canceled) {
847
853
  resolvedData = response;
@@ -912,7 +918,7 @@ var Interpreter = /** @class */ (function () {
912
918
  var canceled = false;
913
919
  var receivers = new Set();
914
920
  var listeners = new Set();
915
- var emitted = undefined;
921
+ var emitted;
916
922
  var receive = function (e) {
917
923
  emitted = e;
918
924
  listeners.forEach(function (listener) { return listener(e); });
@@ -962,7 +968,7 @@ var Interpreter = /** @class */ (function () {
962
968
  };
963
969
  Interpreter.prototype.spawnObservable = function (source, id) {
964
970
  var _this = this;
965
- var emitted = undefined;
971
+ var emitted;
966
972
  var subscription = source.subscribe(function (value) {
967
973
  emitted = value;
968
974
  _this.send(utils_1.toSCXMLEvent(value, { origin: id }));
package/lib/model.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AssignAction, Assigner, PropertyAssigner, ExtractEvent, EventObject } from './types';
1
+ import type { AssignAction, Assigner, PropertyAssigner, ExtractEvent, EventObject, MachineConfig, StateMachine, MachineOptions } from './types';
2
2
  declare type AnyFunction = (...args: any[]) => any;
3
3
  declare type Cast<A1 extends any, A2 extends any> = A1 extends A2 ? A1 : A2;
4
4
  declare type Compute<A extends any> = {
@@ -10,6 +10,7 @@ export interface Model<TContext, TEvent extends EventObject, TModelCreators = vo
10
10
  assign: <TEventType extends TEvent['type'] = TEvent['type']>(assigner: Assigner<TContext, ExtractEvent<TEvent, TEventType>> | PropertyAssigner<TContext, ExtractEvent<TEvent, TEventType>>, eventType?: TEventType) => AssignAction<TContext, ExtractEvent<TEvent, TEventType>>;
11
11
  events: Prop<TModelCreators, 'events'>;
12
12
  reset: () => AssignAction<TContext, any>;
13
+ createMachine: (config: MachineConfig<TContext, any, TEvent>, implementations?: Partial<MachineOptions<TContext, TEvent>>) => StateMachine<TContext, any, TEvent, any>;
13
14
  }
14
15
  export declare type ModelContextFrom<TModel extends Model<any, any, any>> = TModel extends Model<infer TContext, any, any> ? TContext : never;
15
16
  export declare type ModelEventsFrom<TModel extends Model<any, any, any>> = TModel extends Model<any, infer TEvent, any> ? TEvent : never;
package/lib/model.js CHANGED
@@ -34,6 +34,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
35
  exports.createModel = void 0;
36
36
  var actions_1 = require("./actions");
37
+ var Machine_1 = require("./Machine");
37
38
  var utils_1 = require("./utils");
38
39
  function createModel(initialContext, creators) {
39
40
  var eventCreators = creators === null || creators === void 0 ? void 0 : creators.events;
@@ -49,7 +50,10 @@ function createModel(initialContext, creators) {
49
50
  return (__assign(__assign({}, fn.apply(void 0, __spreadArray([], __read(args)))), { type: eventType }));
50
51
  }; })
51
52
  : undefined),
52
- reset: function () { return actions_1.assign(initialContext); }
53
+ reset: function () { return actions_1.assign(initialContext); },
54
+ createMachine: function (config, implementations) {
55
+ return Machine_1.createMachine('context' in config ? config : __assign(__assign({}, config), { context: initialContext }), implementations);
56
+ }
53
57
  };
54
58
  return model;
55
59
  }
package/lib/types.d.ts CHANGED
@@ -152,7 +152,7 @@ export interface InvokeMeta {
152
152
  * @param context The current machine `context`
153
153
  * @param event The event that invoked the service
154
154
  */
155
- export declare type InvokeCreator<TContext, TEvent extends EventObject, TFinalContext = any> = (context: TContext, event: TEvent, meta: InvokeMeta) => PromiseLike<TFinalContext> | StateMachine<TFinalContext, any, any> | Subscribable<EventObject> | InvokeCallback<any, TEvent>;
155
+ export declare type InvokeCreator<TContext, TEvent extends EventObject, TFinalContext = any> = (context: TContext, event: TEvent, meta: InvokeMeta) => PromiseLike<TFinalContext> | StateMachine<TFinalContext, any, any> | Subscribable<EventObject> | InvokeCallback<any, TEvent> | Behavior<any>;
156
156
  export interface InvokeDefinition<TContext, TEvent extends EventObject> extends ActivityDefinition<TContext, TEvent> {
157
157
  /**
158
158
  * The source of the machine to be invoked, or the machine itself.
@@ -878,7 +878,7 @@ export interface Subscribable<T> {
878
878
  subscribe(observer: Observer<T>): Subscription;
879
879
  subscribe(next: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;
880
880
  }
881
- export declare type Spawnable = StateMachine<any, any, any> | Promise<any> | InvokeCallback | Subscribable<any>;
881
+ export declare type Spawnable = StateMachine<any, any, any> | PromiseLike<any> | InvokeCallback | Subscribable<any> | Behavior<any>;
882
882
  export declare type ExtractEvent<TEvent extends EventObject, TEventType extends TEvent['type']> = TEvent extends {
883
883
  type: TEventType;
884
884
  } ? TEvent : never;
@@ -896,13 +896,24 @@ export interface ActorRef<TEvent extends EventObject, TEmitted = any> extends Su
896
896
  * @deprecated Use `ActorRef` instead.
897
897
  */
898
898
  export declare type SpawnedActorRef<TEvent extends EventObject, TEmitted = any> = ActorRef<TEvent, TEmitted>;
899
- export declare type ActorRefFrom<T extends StateMachine<any, any, any> | Promise<any>> = T extends StateMachine<infer TContext, any, infer TEvent, infer TTypestate> ? ActorRef<TEvent, State<TContext, TEvent, any, TTypestate>> & {
899
+ export declare type ActorRefFrom<T extends StateMachine<any, any, any> | Promise<any> | Behavior<any>> = T extends StateMachine<infer TContext, any, infer TEvent, infer TTypestate> ? ActorRef<TEvent, State<TContext, TEvent, any, TTypestate>> & {
900
900
  /**
901
901
  * @deprecated Use `.getSnapshot()` instead.
902
902
  */
903
903
  state: State<TContext, TEvent, any, TTypestate>;
904
- } : T extends Promise<infer U> ? ActorRef<never, U> : never;
904
+ } : T extends Promise<infer U> ? ActorRef<never, U> : T extends Behavior<infer TEvent, infer TEmitted> ? ActorRef<TEvent, TEmitted> : never;
905
905
  export declare type AnyInterpreter = Interpreter<any, any, any, any>;
906
906
  export declare type InterpreterFrom<T extends StateMachine<any, any, any, any>> = T extends StateMachine<infer TContext, infer TStateSchema, infer TEvent, infer TTypestate> ? Interpreter<TContext, TStateSchema, TEvent, TTypestate> : never;
907
+ export interface ActorContext<TEvent extends EventObject, TEmitted> {
908
+ parent?: ActorRef<any, any>;
909
+ self: ActorRef<TEvent, TEmitted>;
910
+ id: string;
911
+ observers: Set<Observer<TEmitted>>;
912
+ }
913
+ export interface Behavior<TEvent extends EventObject, TEmitted = any> {
914
+ transition: (state: TEmitted, event: TEvent, actorCtx: ActorContext<TEvent, TEmitted>) => TEmitted;
915
+ initialState: TEmitted;
916
+ start?: (actorCtx: ActorContext<TEvent, TEmitted>) => TEmitted;
917
+ }
907
918
  export {};
908
919
  //# sourceMappingURL=types.d.ts.map
package/lib/utils.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Event, StateValue, ActionType, Action, EventObject, PropertyMapper, Mapper, EventType, HistoryValue, AssignAction, Condition, Subscribable, StateMachine, ConditionPredicate, SCXML, StateLike, EventData, TransitionConfig, TransitionConfigTarget, NullEvent, SingleOrArray, Guard, InvokeSourceDefinition } from './types';
1
+ import { Event, StateValue, ActionType, Action, EventObject, PropertyMapper, Mapper, EventType, HistoryValue, AssignAction, Condition, Subscribable, StateMachine, ConditionPredicate, SCXML, StateLike, EventData, TransitionConfig, TransitionConfigTarget, NullEvent, SingleOrArray, Guard, InvokeSourceDefinition, Observer, Behavior } from './types';
2
2
  import { StateNode } from './StateNode';
3
- import { Observer, State } from '.';
3
+ import { State } from './State';
4
4
  import { Actor } from './Actor';
5
5
  export declare function keys<T extends object>(value: T): Array<keyof T & string>;
6
6
  export declare function matchesState(parentStateId: StateValue, childStateId: StateValue, delimiter?: string): boolean;
@@ -40,6 +40,7 @@ export declare function toArray<T>(value: T[] | T | undefined): T[];
40
40
  export declare function mapContext<TContext, TEvent extends EventObject>(mapper: Mapper<TContext, TEvent, any> | PropertyMapper<TContext, TEvent, any>, context: TContext, _event: SCXML.Event<TEvent>): any;
41
41
  export declare function isBuiltInEvent(eventType: EventType): boolean;
42
42
  export declare function isPromiseLike(value: any): value is PromiseLike<any>;
43
+ export declare function isBehavior(value: any): value is Behavior<any, any>;
43
44
  export declare function partition<T, A extends T, B extends T>(items: T[], predicate: (item: T) => item is A): [A[], B[]];
44
45
  export declare function updateHistoryStates(hist: HistoryValue, stateValue: StateValue): Record<string, HistoryValue | undefined>;
45
46
  export declare function updateHistoryValue(hist: HistoryValue, stateValue: StateValue): HistoryValue;
package/lib/utils.js CHANGED
@@ -43,7 +43,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
43
43
  return to;
44
44
  };
45
45
  Object.defineProperty(exports, "__esModule", { value: true });
46
- exports.toObserver = exports.toInvokeSource = exports.evaluateGuard = exports.reportUnhandledExceptionOnInvocation = exports.normalizeTarget = exports.toTransitionConfigArray = exports.toSCXMLEvent = exports.toEventObject = exports.uniqueId = exports.isActor = exports.isMachine = exports.symbolObservable = exports.isObservable = exports.toGuard = exports.isString = exports.isFunction = exports.isArray = exports.warn = exports.updateContext = exports.updateHistoryValue = exports.updateHistoryStates = exports.partition = exports.isPromiseLike = exports.isBuiltInEvent = exports.mapContext = exports.toArray = exports.toArrayStrict = exports.flatten = exports.pathsToStateValue = exports.toStatePaths = exports.nestedPath = exports.path = exports.mapFilterValues = exports.mapValues = exports.pathToStateValue = exports.toStateValue = exports.isStateLike = exports.toStatePath = exports.getActionType = exports.getEventType = exports.matchesState = exports.keys = void 0;
46
+ exports.toObserver = exports.toInvokeSource = exports.evaluateGuard = exports.reportUnhandledExceptionOnInvocation = exports.normalizeTarget = exports.toTransitionConfigArray = exports.toSCXMLEvent = exports.toEventObject = exports.uniqueId = exports.isActor = exports.isMachine = exports.symbolObservable = exports.isObservable = exports.toGuard = exports.isString = exports.isFunction = exports.isArray = exports.warn = exports.updateContext = exports.updateHistoryValue = exports.updateHistoryStates = exports.partition = exports.isBehavior = exports.isPromiseLike = exports.isBuiltInEvent = exports.mapContext = exports.toArray = exports.toArrayStrict = exports.flatten = exports.pathsToStateValue = exports.toStatePaths = exports.nestedPath = exports.path = exports.mapFilterValues = exports.mapValues = exports.pathToStateValue = exports.toStateValue = exports.isStateLike = exports.toStatePath = exports.getActionType = exports.getEventType = exports.matchesState = exports.keys = void 0;
47
47
  var constants_1 = require("./constants");
48
48
  var environment_1 = require("./environment");
49
49
  function keys(value) {
@@ -345,6 +345,13 @@ function isPromiseLike(value) {
345
345
  return false;
346
346
  }
347
347
  exports.isPromiseLike = isPromiseLike;
348
+ function isBehavior(value) {
349
+ return (value !== null &&
350
+ typeof value === 'object' &&
351
+ 'transition' in value &&
352
+ typeof value.transition === 'function');
353
+ }
354
+ exports.isBehavior = isBehavior;
348
355
  function partition(items, predicate) {
349
356
  var e_6, _a;
350
357
  var _b = __read([[], []], 2), truthy = _b[0], falsy = _b[1];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xstate",
3
- "version": "4.20.2",
3
+ "version": "4.22.0",
4
4
  "description": "Finite State Machines and Statecharts for the Modern Web.",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",