UNPKG

16.5 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var _tslib = require('./_virtual/_tslib.js');
6var types = require('./types.js');
7var actionTypes = require('./actionTypes.js');
8var utils = require('./utils.js');
9var environment = require('./environment.js');
10
11var initEvent = /*#__PURE__*/utils.toSCXMLEvent({
12 type: actionTypes.init
13});
14function getActionFunction(actionType, actionFunctionMap) {
15 return actionFunctionMap ? actionFunctionMap[actionType] || undefined : undefined;
16}
17function toActionObject(action, actionFunctionMap) {
18 var actionObject;
19
20 if (utils.isString(action) || typeof action === 'number') {
21 var exec = getActionFunction(action, actionFunctionMap);
22
23 if (utils.isFunction(exec)) {
24 actionObject = {
25 type: action,
26 exec: exec
27 };
28 } else if (exec) {
29 actionObject = exec;
30 } else {
31 actionObject = {
32 type: action,
33 exec: undefined
34 };
35 }
36 } else if (utils.isFunction(action)) {
37 actionObject = {
38 // Convert action to string if unnamed
39 type: action.name || action.toString(),
40 exec: action
41 };
42 } else {
43 var exec = getActionFunction(action.type, actionFunctionMap);
44
45 if (utils.isFunction(exec)) {
46 actionObject = _tslib.__assign(_tslib.__assign({}, action), {
47 exec: exec
48 });
49 } else if (exec) {
50 var actionType = exec.type || action.type;
51 actionObject = _tslib.__assign(_tslib.__assign(_tslib.__assign({}, exec), action), {
52 type: actionType
53 });
54 } else {
55 actionObject = action;
56 }
57 }
58
59 return actionObject;
60}
61var toActionObjects = function (action, actionFunctionMap) {
62 if (!action) {
63 return [];
64 }
65
66 var actions = utils.isArray(action) ? action : [action];
67 return actions.map(function (subAction) {
68 return toActionObject(subAction, actionFunctionMap);
69 });
70};
71function toActivityDefinition(action) {
72 var actionObject = toActionObject(action);
73 return _tslib.__assign(_tslib.__assign({
74 id: utils.isString(action) ? action : actionObject.id
75 }, actionObject), {
76 type: actionObject.type
77 });
78}
79/**
80 * Raises an event. This places the event in the internal event queue, so that
81 * the event is immediately consumed by the machine in the current step.
82 *
83 * @param eventType The event to raise.
84 */
85
86function raise(event) {
87 if (!utils.isString(event)) {
88 return send(event, {
89 to: types.SpecialTargets.Internal
90 });
91 }
92
93 return {
94 type: actionTypes.raise,
95 event: event
96 };
97}
98function resolveRaise(action) {
99 return {
100 type: actionTypes.raise,
101 _event: utils.toSCXMLEvent(action.event)
102 };
103}
104/**
105 * Sends an event. This returns an action that will be read by an interpreter to
106 * send the event in the next step, after the current step is finished executing.
107 *
108 * @param event The event to send.
109 * @param options Options to pass into the send event:
110 * - `id` - The unique send event identifier (used with `cancel()`).
111 * - `delay` - The number of milliseconds to delay the sending of the event.
112 * - `to` - The target of this event (by default, the machine the event was sent from).
113 */
114
115function send(event, options) {
116 return {
117 to: options ? options.to : undefined,
118 type: actionTypes.send,
119 event: utils.isFunction(event) ? event : utils.toEventObject(event),
120 delay: options ? options.delay : undefined,
121 id: options && options.id !== undefined ? options.id : utils.isFunction(event) ? event.name : utils.getEventType(event)
122 };
123}
124function resolveSend(action, ctx, _event, delaysMap) {
125 var meta = {
126 _event: _event
127 }; // TODO: helper function for resolving Expr
128
129 var resolvedEvent = utils.toSCXMLEvent(utils.isFunction(action.event) ? action.event(ctx, _event.data, meta) : action.event);
130 var resolvedDelay;
131
132 if (utils.isString(action.delay)) {
133 var configDelay = delaysMap && delaysMap[action.delay];
134 resolvedDelay = utils.isFunction(configDelay) ? configDelay(ctx, _event.data, meta) : configDelay;
135 } else {
136 resolvedDelay = utils.isFunction(action.delay) ? action.delay(ctx, _event.data, meta) : action.delay;
137 }
138
139 var resolvedTarget = utils.isFunction(action.to) ? action.to(ctx, _event.data, meta) : action.to;
140 return _tslib.__assign(_tslib.__assign({}, action), {
141 to: resolvedTarget,
142 _event: resolvedEvent,
143 event: resolvedEvent.data,
144 delay: resolvedDelay
145 });
146}
147/**
148 * Sends an event to this machine's parent.
149 *
150 * @param event The event to send to the parent machine.
151 * @param options Options to pass into the send event.
152 */
153
154function sendParent(event, options) {
155 return send(event, _tslib.__assign(_tslib.__assign({}, options), {
156 to: types.SpecialTargets.Parent
157 }));
158}
159/**
160 * Sends an event to an actor.
161 *
162 * @param actor The `ActorRef` to send the event to.
163 * @param event The event to send, or an expression that evaluates to the event to send
164 * @param options Send action options
165 * @returns An XState send action object
166 */
167
168function sendTo(actor, event, options) {
169 return send(event, _tslib.__assign(_tslib.__assign({}, options), {
170 to: actor
171 }));
172}
173/**
174 * Sends an update event to this machine's parent.
175 */
176
177function sendUpdate() {
178 return sendParent(actionTypes.update);
179}
180/**
181 * Sends an event back to the sender of the original event.
182 *
183 * @param event The event to send back to the sender
184 * @param options Options to pass into the send event
185 */
186
187function respond(event, options) {
188 return send(event, _tslib.__assign(_tslib.__assign({}, options), {
189 to: function (_, __, _a) {
190 var _event = _a._event;
191 return _event.origin; // TODO: handle when _event.origin is undefined
192 }
193 }));
194}
195
196var defaultLogExpr = function (context, event) {
197 return {
198 context: context,
199 event: event
200 };
201};
202/**
203 *
204 * @param expr The expression function to evaluate which will be logged.
205 * Takes in 2 arguments:
206 * - `ctx` - the current state context
207 * - `event` - the event that caused this action to be executed.
208 * @param label The label to give to the logged expression.
209 */
210
211
212function log(expr, label) {
213 if (expr === void 0) {
214 expr = defaultLogExpr;
215 }
216
217 return {
218 type: actionTypes.log,
219 label: label,
220 expr: expr
221 };
222}
223var resolveLog = function (action, ctx, _event) {
224 return _tslib.__assign(_tslib.__assign({}, action), {
225 value: utils.isString(action.expr) ? action.expr : action.expr(ctx, _event.data, {
226 _event: _event
227 })
228 });
229};
230/**
231 * Cancels an in-flight `send(...)` action. A canceled sent action will not
232 * be executed, nor will its event be sent, unless it has already been sent
233 * (e.g., if `cancel(...)` is called after the `send(...)` action's `delay`).
234 *
235 * @param sendId The `id` of the `send(...)` action to cancel.
236 */
237
238var cancel = function (sendId) {
239 return {
240 type: actionTypes.cancel,
241 sendId: sendId
242 };
243};
244/**
245 * Starts an activity.
246 *
247 * @param activity The activity to start.
248 */
249
250function start(activity) {
251 var activityDef = toActivityDefinition(activity);
252 return {
253 type: types.ActionTypes.Start,
254 activity: activityDef,
255 exec: undefined
256 };
257}
258/**
259 * Stops an activity.
260 *
261 * @param actorRef The activity to stop.
262 */
263
264function stop(actorRef) {
265 var activity = utils.isFunction(actorRef) ? actorRef : toActivityDefinition(actorRef);
266 return {
267 type: types.ActionTypes.Stop,
268 activity: activity,
269 exec: undefined
270 };
271}
272function resolveStop(action, context, _event) {
273 var actorRefOrString = utils.isFunction(action.activity) ? action.activity(context, _event.data) : action.activity;
274 var resolvedActorRef = typeof actorRefOrString === 'string' ? {
275 id: actorRefOrString
276 } : actorRefOrString;
277 var actionObject = {
278 type: types.ActionTypes.Stop,
279 activity: resolvedActorRef
280 };
281 return actionObject;
282}
283/**
284 * Updates the current context of the machine.
285 *
286 * @param assignment An object that represents the partial context to update.
287 */
288
289var assign = function (assignment) {
290 return {
291 type: actionTypes.assign,
292 assignment: assignment
293 };
294};
295function isActionObject(action) {
296 return typeof action === 'object' && 'type' in action;
297}
298/**
299 * Returns an event type that represents an implicit event that
300 * is sent after the specified `delay`.
301 *
302 * @param delayRef The delay in milliseconds
303 * @param id The state node ID where this event is handled
304 */
305
306function after(delayRef, id) {
307 var idSuffix = id ? "#".concat(id) : '';
308 return "".concat(types.ActionTypes.After, "(").concat(delayRef, ")").concat(idSuffix);
309}
310/**
311 * Returns an event that represents that a final state node
312 * has been reached in the parent state node.
313 *
314 * @param id The final state node's parent state node `id`
315 * @param data The data to pass into the event
316 */
317
318function done(id, data) {
319 var type = "".concat(types.ActionTypes.DoneState, ".").concat(id);
320 var eventObject = {
321 type: type,
322 data: data
323 };
324
325 eventObject.toString = function () {
326 return type;
327 };
328
329 return eventObject;
330}
331/**
332 * Returns an event that represents that an invoked service has terminated.
333 *
334 * An invoked service is terminated when it has reached a top-level final state node,
335 * but not when it is canceled.
336 *
337 * @param id The final state node ID
338 * @param data The data to pass into the event
339 */
340
341function doneInvoke(id, data) {
342 var type = "".concat(types.ActionTypes.DoneInvoke, ".").concat(id);
343 var eventObject = {
344 type: type,
345 data: data
346 };
347
348 eventObject.toString = function () {
349 return type;
350 };
351
352 return eventObject;
353}
354function error(id, data) {
355 var type = "".concat(types.ActionTypes.ErrorPlatform, ".").concat(id);
356 var eventObject = {
357 type: type,
358 data: data
359 };
360
361 eventObject.toString = function () {
362 return type;
363 };
364
365 return eventObject;
366}
367function pure(getActions) {
368 return {
369 type: types.ActionTypes.Pure,
370 get: getActions
371 };
372}
373/**
374 * Forwards (sends) an event to a specified service.
375 *
376 * @param target The target service to forward the event to.
377 * @param options Options to pass into the send action creator.
378 */
379
380function forwardTo(target, options) {
381 return send(function (_, event) {
382 return event;
383 }, _tslib.__assign(_tslib.__assign({}, options), {
384 to: target
385 }));
386}
387/**
388 * Escalates an error by sending it as an event to this machine's parent.
389 *
390 * @param errorData The error data to send, or the expression function that
391 * takes in the `context`, `event`, and `meta`, and returns the error data to send.
392 * @param options Options to pass into the send action creator.
393 */
394
395function escalate(errorData, options) {
396 return sendParent(function (context, event, meta) {
397 return {
398 type: actionTypes.error,
399 data: utils.isFunction(errorData) ? errorData(context, event, meta) : errorData
400 };
401 }, _tslib.__assign(_tslib.__assign({}, options), {
402 to: types.SpecialTargets.Parent
403 }));
404}
405function choose(conds) {
406 return {
407 type: types.ActionTypes.Choose,
408 conds: conds
409 };
410}
411function resolveActions(machine, currentState, currentContext, _event, actions, preserveActionOrder) {
412 if (preserveActionOrder === void 0) {
413 preserveActionOrder = false;
414 }
415
416 var _a = _tslib.__read(preserveActionOrder ? [[], actions] : utils.partition(actions, function (action) {
417 return action.type === actionTypes.assign;
418 }), 2),
419 assignActions = _a[0],
420 otherActions = _a[1];
421
422 var updatedContext = assignActions.length ? utils.updateContext(currentContext, _event, assignActions, currentState) : currentContext;
423 var preservedContexts = preserveActionOrder ? [currentContext] : undefined;
424 var resolvedActions = utils.flatten(otherActions.map(function (actionObject) {
425 var _a;
426
427 switch (actionObject.type) {
428 case actionTypes.raise:
429 return resolveRaise(actionObject);
430
431 case actionTypes.send:
432 var sendAction = resolveSend(actionObject, updatedContext, _event, machine.options.delays); // TODO: fix ActionTypes.Init
433
434 if (!environment.IS_PRODUCTION) {
435 // warn after resolving as we can create better contextual message here
436 utils.warn(!utils.isString(actionObject.delay) || typeof sendAction.delay === 'number', // tslint:disable-next-line:max-line-length
437 "No delay reference for delay expression '".concat(actionObject.delay, "' was found on machine '").concat(machine.id, "'"));
438 }
439
440 return sendAction;
441
442 case actionTypes.log:
443 return resolveLog(actionObject, updatedContext, _event);
444
445 case actionTypes.choose:
446 {
447 var chooseAction = actionObject;
448 var matchedActions = (_a = chooseAction.conds.find(function (condition) {
449 var guard = utils.toGuard(condition.cond, machine.options.guards);
450 return !guard || utils.evaluateGuard(machine, guard, updatedContext, _event, currentState);
451 })) === null || _a === void 0 ? void 0 : _a.actions;
452
453 if (!matchedActions) {
454 return [];
455 }
456
457 var _b = _tslib.__read(resolveActions(machine, currentState, updatedContext, _event, toActionObjects(utils.toArray(matchedActions), machine.options.actions), preserveActionOrder), 2),
458 resolvedActionsFromChoose = _b[0],
459 resolvedContextFromChoose = _b[1];
460
461 updatedContext = resolvedContextFromChoose;
462 preservedContexts === null || preservedContexts === void 0 ? void 0 : preservedContexts.push(updatedContext);
463 return resolvedActionsFromChoose;
464 }
465
466 case actionTypes.pure:
467 {
468 var matchedActions = actionObject.get(updatedContext, _event.data);
469
470 if (!matchedActions) {
471 return [];
472 }
473
474 var _c = _tslib.__read(resolveActions(machine, currentState, updatedContext, _event, toActionObjects(utils.toArray(matchedActions), machine.options.actions), preserveActionOrder), 2),
475 resolvedActionsFromPure = _c[0],
476 resolvedContext = _c[1];
477
478 updatedContext = resolvedContext;
479 preservedContexts === null || preservedContexts === void 0 ? void 0 : preservedContexts.push(updatedContext);
480 return resolvedActionsFromPure;
481 }
482
483 case actionTypes.stop:
484 {
485 return resolveStop(actionObject, updatedContext, _event);
486 }
487
488 case actionTypes.assign:
489 {
490 updatedContext = utils.updateContext(updatedContext, _event, [actionObject], currentState);
491 preservedContexts === null || preservedContexts === void 0 ? void 0 : preservedContexts.push(updatedContext);
492 break;
493 }
494
495 default:
496 var resolvedActionObject = toActionObject(actionObject, machine.options.actions);
497 var exec_1 = resolvedActionObject.exec;
498
499 if (exec_1 && preservedContexts) {
500 var contextIndex_1 = preservedContexts.length - 1;
501 resolvedActionObject = _tslib.__assign(_tslib.__assign({}, resolvedActionObject), {
502 exec: function (_ctx) {
503 var args = [];
504
505 for (var _i = 1; _i < arguments.length; _i++) {
506 args[_i - 1] = arguments[_i];
507 }
508
509 exec_1.apply(void 0, _tslib.__spreadArray([preservedContexts[contextIndex_1]], _tslib.__read(args), false));
510 }
511 });
512 }
513
514 return resolvedActionObject;
515 }
516 }).filter(function (a) {
517 return !!a;
518 }));
519 return [resolvedActions, updatedContext];
520}
521
522exports.actionTypes = actionTypes;
523exports.after = after;
524exports.assign = assign;
525exports.cancel = cancel;
526exports.choose = choose;
527exports.done = done;
528exports.doneInvoke = doneInvoke;
529exports.error = error;
530exports.escalate = escalate;
531exports.forwardTo = forwardTo;
532exports.getActionFunction = getActionFunction;
533exports.initEvent = initEvent;
534exports.isActionObject = isActionObject;
535exports.log = log;
536exports.pure = pure;
537exports.raise = raise;
538exports.resolveActions = resolveActions;
539exports.resolveLog = resolveLog;
540exports.resolveRaise = resolveRaise;
541exports.resolveSend = resolveSend;
542exports.resolveStop = resolveStop;
543exports.respond = respond;
544exports.send = send;
545exports.sendParent = sendParent;
546exports.sendTo = sendTo;
547exports.sendUpdate = sendUpdate;
548exports.start = start;
549exports.stop = stop;
550exports.toActionObject = toActionObject;
551exports.toActionObjects = toActionObjects;
552exports.toActivityDefinition = toActivityDefinition;