UNPKG

7.95 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var _tslib = require('./_virtual/_tslib.js');
6var constants = require('./constants.js');
7var utils = require('./utils.js');
8var stateUtils = require('./stateUtils.js');
9var actions = require('./actions.js');
10var environment = require('./environment.js');
11
12function stateValuesEqual(a, b) {
13 if (a === b) {
14 return true;
15 }
16
17 if (a === undefined || b === undefined) {
18 return false;
19 }
20
21 if (utils.isString(a) || utils.isString(b)) {
22 return a === b;
23 }
24
25 var aKeys = Object.keys(a);
26 var bKeys = Object.keys(b);
27 return aKeys.length === bKeys.length && aKeys.every(function (key) {
28 return stateValuesEqual(a[key], b[key]);
29 });
30}
31function isStateConfig(state) {
32 if (typeof state !== 'object' || state === null) {
33 return false;
34 }
35
36 return 'value' in state && '_event' in state;
37}
38/**
39 * @deprecated Use `isStateConfig(object)` or `state instanceof State` instead.
40 */
41
42var isState = isStateConfig;
43function bindActionToState(action, state) {
44 var exec = action.exec;
45
46 var boundAction = _tslib.__assign(_tslib.__assign({}, action), {
47 exec: exec !== undefined ? function () {
48 return exec(state.context, state.event, {
49 action: action,
50 state: state,
51 _event: state._event
52 });
53 } : undefined
54 });
55
56 return boundAction;
57}
58
59var State =
60/*#__PURE__*/
61
62/** @class */
63function () {
64 /**
65 * Creates a new State instance.
66 * @param value The state value
67 * @param context The extended state
68 * @param historyValue The tree representing historical values of the state nodes
69 * @param history The previous state
70 * @param actions An array of action objects to execute as side-effects
71 * @param activities A mapping of activities and whether they are started (`true`) or stopped (`false`).
72 * @param meta
73 * @param events Internal event queue. Should be empty with run-to-completion semantics.
74 * @param configuration
75 */
76 function State(config) {
77 var _this = this;
78
79 var _a;
80
81 this.actions = [];
82 this.activities = constants.EMPTY_ACTIVITY_MAP;
83 this.meta = {};
84 this.events = [];
85 this.value = config.value;
86 this.context = config.context;
87 this._event = config._event;
88 this._sessionid = config._sessionid;
89 this.event = this._event.data;
90 this.historyValue = config.historyValue;
91 this.history = config.history;
92 this.actions = config.actions || [];
93 this.activities = config.activities || constants.EMPTY_ACTIVITY_MAP;
94 this.meta = stateUtils.getMeta(config.configuration);
95 this.events = config.events || [];
96 this.matches = this.matches.bind(this);
97 this.toStrings = this.toStrings.bind(this);
98 this.configuration = config.configuration;
99 this.transitions = config.transitions;
100 this.children = config.children;
101 this.done = !!config.done;
102 this.tags = (_a = Array.isArray(config.tags) ? new Set(config.tags) : config.tags) !== null && _a !== void 0 ? _a : new Set();
103 this.machine = config.machine;
104 Object.defineProperty(this, 'nextEvents', {
105 get: function () {
106 return stateUtils.nextEvents(_this.configuration);
107 }
108 });
109 }
110 /**
111 * Creates a new State instance for the given `stateValue` and `context`.
112 * @param stateValue
113 * @param context
114 */
115
116
117 State.from = function (stateValue, context) {
118 if (stateValue instanceof State) {
119 if (stateValue.context !== context) {
120 return new State({
121 value: stateValue.value,
122 context: context,
123 _event: stateValue._event,
124 _sessionid: null,
125 historyValue: stateValue.historyValue,
126 history: stateValue.history,
127 actions: [],
128 activities: stateValue.activities,
129 meta: {},
130 events: [],
131 configuration: [],
132 transitions: [],
133 children: {}
134 });
135 }
136
137 return stateValue;
138 }
139
140 var _event = actions.initEvent;
141 return new State({
142 value: stateValue,
143 context: context,
144 _event: _event,
145 _sessionid: null,
146 historyValue: undefined,
147 history: undefined,
148 actions: [],
149 activities: undefined,
150 meta: undefined,
151 events: [],
152 configuration: [],
153 transitions: [],
154 children: {}
155 });
156 };
157 /**
158 * Creates a new State instance for the given `config`.
159 * @param config The state config
160 */
161
162
163 State.create = function (config) {
164 return new State(config);
165 };
166 /**
167 * Creates a new `State` instance for the given `stateValue` and `context` with no actions (side-effects).
168 * @param stateValue
169 * @param context
170 */
171
172
173 State.inert = function (stateValue, context) {
174 if (stateValue instanceof State) {
175 if (!stateValue.actions.length) {
176 return stateValue;
177 }
178
179 var _event = actions.initEvent;
180 return new State({
181 value: stateValue.value,
182 context: context,
183 _event: _event,
184 _sessionid: null,
185 historyValue: stateValue.historyValue,
186 history: stateValue.history,
187 activities: stateValue.activities,
188 configuration: stateValue.configuration,
189 transitions: [],
190 children: {}
191 });
192 }
193
194 return State.from(stateValue, context);
195 };
196 /**
197 * Returns an array of all the string leaf state node paths.
198 * @param stateValue
199 * @param delimiter The character(s) that separate each subpath in the string state node path.
200 */
201
202
203 State.prototype.toStrings = function (stateValue, delimiter) {
204 var _this = this;
205
206 if (stateValue === void 0) {
207 stateValue = this.value;
208 }
209
210 if (delimiter === void 0) {
211 delimiter = '.';
212 }
213
214 if (utils.isString(stateValue)) {
215 return [stateValue];
216 }
217
218 var valueKeys = Object.keys(stateValue);
219 return valueKeys.concat.apply(valueKeys, _tslib.__spreadArray([], _tslib.__read(valueKeys.map(function (key) {
220 return _this.toStrings(stateValue[key], delimiter).map(function (s) {
221 return key + delimiter + s;
222 });
223 })), false));
224 };
225
226 State.prototype.toJSON = function () {
227 var _a = this;
228 _a.configuration;
229 _a.transitions;
230 var tags = _a.tags;
231 _a.machine;
232 var jsonValues = _tslib.__rest(_a, ["configuration", "transitions", "tags", "machine"]);
233
234 return _tslib.__assign(_tslib.__assign({}, jsonValues), {
235 tags: Array.from(tags)
236 });
237 };
238
239 State.prototype.matches = function (parentStateValue) {
240 return utils.matchesState(parentStateValue, this.value);
241 };
242 /**
243 * Whether the current state configuration has a state node with the specified `tag`.
244 * @param tag
245 */
246
247
248 State.prototype.hasTag = function (tag) {
249 return this.tags.has(tag);
250 };
251 /**
252 * Determines whether sending the `event` will cause a non-forbidden transition
253 * to be selected, even if the transitions have no actions nor
254 * change the state value.
255 *
256 * @param event The event to test
257 * @returns Whether the event will cause a transition
258 */
259
260
261 State.prototype.can = function (event) {
262 var _a;
263
264 if (environment.IS_PRODUCTION) {
265 utils.warn(!!this.machine, "state.can(...) used outside of a machine-created State object; this will always return false.");
266 }
267
268 var transitionData = (_a = this.machine) === null || _a === void 0 ? void 0 : _a.getTransitionData(this, event);
269 return !!(transitionData === null || transitionData === void 0 ? void 0 : transitionData.transitions.length) && // Check that at least one transition is not forbidden
270 transitionData.transitions.some(function (t) {
271 return t.target !== undefined || t.actions.length;
272 });
273 };
274
275 return State;
276}();
277
278exports.State = State;
279exports.bindActionToState = bindActionToState;
280exports.isState = isState;
281exports.isStateConfig = isStateConfig;
282exports.stateValuesEqual = stateValuesEqual;