utils.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var _tslib = require('./_virtual/_tslib.js');
  4. var types = require('./types.js');
  5. var actionTypes = require('./actionTypes.js');
  6. var constants = require('./constants.js');
  7. var environment = require('./environment.js');
  8. var _a;
  9. function keys(value) {
  10. return Object.keys(value);
  11. }
  12. function matchesState(parentStateId, childStateId, delimiter) {
  13. if (delimiter === void 0) {
  14. delimiter = constants.STATE_DELIMITER;
  15. }
  16. var parentStateValue = toStateValue(parentStateId, delimiter);
  17. var childStateValue = toStateValue(childStateId, delimiter);
  18. if (isString(childStateValue)) {
  19. if (isString(parentStateValue)) {
  20. return childStateValue === parentStateValue;
  21. } // Parent more specific than child
  22. return false;
  23. }
  24. if (isString(parentStateValue)) {
  25. return parentStateValue in childStateValue;
  26. }
  27. return Object.keys(parentStateValue).every(function (key) {
  28. if (!(key in childStateValue)) {
  29. return false;
  30. }
  31. return matchesState(parentStateValue[key], childStateValue[key]);
  32. });
  33. }
  34. function getEventType(event) {
  35. try {
  36. return isString(event) || typeof event === 'number' ? "".concat(event) : event.type;
  37. } catch (e) {
  38. throw new Error('Events must be strings or objects with a string event.type property.');
  39. }
  40. }
  41. function getActionType(action) {
  42. try {
  43. return isString(action) || typeof action === 'number' ? "".concat(action) : isFunction(action) ? action.name : action.type;
  44. } catch (e) {
  45. throw new Error('Actions must be strings or objects with a string action.type property.');
  46. }
  47. }
  48. function toStatePath(stateId, delimiter) {
  49. try {
  50. if (isArray(stateId)) {
  51. return stateId;
  52. }
  53. return stateId.toString().split(delimiter);
  54. } catch (e) {
  55. throw new Error("'".concat(stateId, "' is not a valid state path."));
  56. }
  57. }
  58. function isStateLike(state) {
  59. return typeof state === 'object' && 'value' in state && 'context' in state && 'event' in state && '_event' in state;
  60. }
  61. function toStateValue(stateValue, delimiter) {
  62. if (isStateLike(stateValue)) {
  63. return stateValue.value;
  64. }
  65. if (isArray(stateValue)) {
  66. return pathToStateValue(stateValue);
  67. }
  68. if (typeof stateValue !== 'string') {
  69. return stateValue;
  70. }
  71. var statePath = toStatePath(stateValue, delimiter);
  72. return pathToStateValue(statePath);
  73. }
  74. function pathToStateValue(statePath) {
  75. if (statePath.length === 1) {
  76. return statePath[0];
  77. }
  78. var value = {};
  79. var marker = value;
  80. for (var i = 0; i < statePath.length - 1; i++) {
  81. if (i === statePath.length - 2) {
  82. marker[statePath[i]] = statePath[i + 1];
  83. } else {
  84. marker[statePath[i]] = {};
  85. marker = marker[statePath[i]];
  86. }
  87. }
  88. return value;
  89. }
  90. function mapValues(collection, iteratee) {
  91. var result = {};
  92. var collectionKeys = Object.keys(collection);
  93. for (var i = 0; i < collectionKeys.length; i++) {
  94. var key = collectionKeys[i];
  95. result[key] = iteratee(collection[key], key, collection, i);
  96. }
  97. return result;
  98. }
  99. function mapFilterValues(collection, iteratee, predicate) {
  100. var e_1, _a;
  101. var result = {};
  102. try {
  103. for (var _b = _tslib.__values(Object.keys(collection)), _c = _b.next(); !_c.done; _c = _b.next()) {
  104. var key = _c.value;
  105. var item = collection[key];
  106. if (!predicate(item)) {
  107. continue;
  108. }
  109. result[key] = iteratee(item, key, collection);
  110. }
  111. } catch (e_1_1) {
  112. e_1 = {
  113. error: e_1_1
  114. };
  115. } finally {
  116. try {
  117. if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
  118. } finally {
  119. if (e_1) throw e_1.error;
  120. }
  121. }
  122. return result;
  123. }
  124. /**
  125. * Retrieves a value at the given path.
  126. * @param props The deep path to the prop of the desired value
  127. */
  128. var path = function (props) {
  129. return function (object) {
  130. var e_2, _a;
  131. var result = object;
  132. try {
  133. for (var props_1 = _tslib.__values(props), props_1_1 = props_1.next(); !props_1_1.done; props_1_1 = props_1.next()) {
  134. var prop = props_1_1.value;
  135. result = result[prop];
  136. }
  137. } catch (e_2_1) {
  138. e_2 = {
  139. error: e_2_1
  140. };
  141. } finally {
  142. try {
  143. if (props_1_1 && !props_1_1.done && (_a = props_1.return)) _a.call(props_1);
  144. } finally {
  145. if (e_2) throw e_2.error;
  146. }
  147. }
  148. return result;
  149. };
  150. };
  151. /**
  152. * Retrieves a value at the given path via the nested accessor prop.
  153. * @param props The deep path to the prop of the desired value
  154. */
  155. function nestedPath(props, accessorProp) {
  156. return function (object) {
  157. var e_3, _a;
  158. var result = object;
  159. try {
  160. for (var props_2 = _tslib.__values(props), props_2_1 = props_2.next(); !props_2_1.done; props_2_1 = props_2.next()) {
  161. var prop = props_2_1.value;
  162. result = result[accessorProp][prop];
  163. }
  164. } catch (e_3_1) {
  165. e_3 = {
  166. error: e_3_1
  167. };
  168. } finally {
  169. try {
  170. if (props_2_1 && !props_2_1.done && (_a = props_2.return)) _a.call(props_2);
  171. } finally {
  172. if (e_3) throw e_3.error;
  173. }
  174. }
  175. return result;
  176. };
  177. }
  178. function toStatePaths(stateValue) {
  179. if (!stateValue) {
  180. return [[]];
  181. }
  182. if (isString(stateValue)) {
  183. return [[stateValue]];
  184. }
  185. var result = flatten(Object.keys(stateValue).map(function (key) {
  186. var subStateValue = stateValue[key];
  187. if (typeof subStateValue !== 'string' && (!subStateValue || !Object.keys(subStateValue).length)) {
  188. return [[key]];
  189. }
  190. return toStatePaths(stateValue[key]).map(function (subPath) {
  191. return [key].concat(subPath);
  192. });
  193. }));
  194. return result;
  195. }
  196. function pathsToStateValue(paths) {
  197. var e_4, _a;
  198. var result = {};
  199. if (paths && paths.length === 1 && paths[0].length === 1) {
  200. return paths[0][0];
  201. }
  202. try {
  203. for (var paths_1 = _tslib.__values(paths), paths_1_1 = paths_1.next(); !paths_1_1.done; paths_1_1 = paths_1.next()) {
  204. var currentPath = paths_1_1.value;
  205. var marker = result; // tslint:disable-next-line:prefer-for-of
  206. for (var i = 0; i < currentPath.length; i++) {
  207. var subPath = currentPath[i];
  208. if (i === currentPath.length - 2) {
  209. marker[subPath] = currentPath[i + 1];
  210. break;
  211. }
  212. marker[subPath] = marker[subPath] || {};
  213. marker = marker[subPath];
  214. }
  215. }
  216. } catch (e_4_1) {
  217. e_4 = {
  218. error: e_4_1
  219. };
  220. } finally {
  221. try {
  222. if (paths_1_1 && !paths_1_1.done && (_a = paths_1.return)) _a.call(paths_1);
  223. } finally {
  224. if (e_4) throw e_4.error;
  225. }
  226. }
  227. return result;
  228. }
  229. function flatten(array) {
  230. var _a;
  231. return (_a = []).concat.apply(_a, _tslib.__spreadArray([], _tslib.__read(array), false));
  232. }
  233. function toArrayStrict(value) {
  234. if (isArray(value)) {
  235. return value;
  236. }
  237. return [value];
  238. }
  239. function toArray(value) {
  240. if (value === undefined) {
  241. return [];
  242. }
  243. return toArrayStrict(value);
  244. }
  245. function mapContext(mapper, context, _event) {
  246. var e_5, _a;
  247. if (isFunction(mapper)) {
  248. return mapper(context, _event.data);
  249. }
  250. var result = {};
  251. try {
  252. for (var _b = _tslib.__values(Object.keys(mapper)), _c = _b.next(); !_c.done; _c = _b.next()) {
  253. var key = _c.value;
  254. var subMapper = mapper[key];
  255. if (isFunction(subMapper)) {
  256. result[key] = subMapper(context, _event.data);
  257. } else {
  258. result[key] = subMapper;
  259. }
  260. }
  261. } catch (e_5_1) {
  262. e_5 = {
  263. error: e_5_1
  264. };
  265. } finally {
  266. try {
  267. if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
  268. } finally {
  269. if (e_5) throw e_5.error;
  270. }
  271. }
  272. return result;
  273. }
  274. function isBuiltInEvent(eventType) {
  275. return /^(done|error)\./.test(eventType);
  276. }
  277. function isPromiseLike(value) {
  278. if (value instanceof Promise) {
  279. return true;
  280. } // Check if shape matches the Promise/A+ specification for a "thenable".
  281. if (value !== null && (isFunction(value) || typeof value === 'object') && isFunction(value.then)) {
  282. return true;
  283. }
  284. return false;
  285. }
  286. function isBehavior(value) {
  287. return value !== null && typeof value === 'object' && 'transition' in value && typeof value.transition === 'function';
  288. }
  289. function partition(items, predicate) {
  290. var e_6, _a;
  291. var _b = _tslib.__read([[], []], 2),
  292. truthy = _b[0],
  293. falsy = _b[1];
  294. try {
  295. for (var items_1 = _tslib.__values(items), items_1_1 = items_1.next(); !items_1_1.done; items_1_1 = items_1.next()) {
  296. var item = items_1_1.value;
  297. if (predicate(item)) {
  298. truthy.push(item);
  299. } else {
  300. falsy.push(item);
  301. }
  302. }
  303. } catch (e_6_1) {
  304. e_6 = {
  305. error: e_6_1
  306. };
  307. } finally {
  308. try {
  309. if (items_1_1 && !items_1_1.done && (_a = items_1.return)) _a.call(items_1);
  310. } finally {
  311. if (e_6) throw e_6.error;
  312. }
  313. }
  314. return [truthy, falsy];
  315. }
  316. function updateHistoryStates(hist, stateValue) {
  317. return mapValues(hist.states, function (subHist, key) {
  318. if (!subHist) {
  319. return undefined;
  320. }
  321. var subStateValue = (isString(stateValue) ? undefined : stateValue[key]) || (subHist ? subHist.current : undefined);
  322. if (!subStateValue) {
  323. return undefined;
  324. }
  325. return {
  326. current: subStateValue,
  327. states: updateHistoryStates(subHist, subStateValue)
  328. };
  329. });
  330. }
  331. function updateHistoryValue(hist, stateValue) {
  332. return {
  333. current: stateValue,
  334. states: updateHistoryStates(hist, stateValue)
  335. };
  336. }
  337. function updateContext(context, _event, assignActions, state) {
  338. if (!environment.IS_PRODUCTION) {
  339. exports.warn(!!context, 'Attempting to update undefined context');
  340. }
  341. var updatedContext = context ? assignActions.reduce(function (acc, assignAction) {
  342. var e_7, _a;
  343. var assignment = assignAction.assignment;
  344. var meta = {
  345. state: state,
  346. action: assignAction,
  347. _event: _event
  348. };
  349. var partialUpdate = {};
  350. if (isFunction(assignment)) {
  351. partialUpdate = assignment(acc, _event.data, meta);
  352. } else {
  353. try {
  354. for (var _b = _tslib.__values(Object.keys(assignment)), _c = _b.next(); !_c.done; _c = _b.next()) {
  355. var key = _c.value;
  356. var propAssignment = assignment[key];
  357. partialUpdate[key] = isFunction(propAssignment) ? propAssignment(acc, _event.data, meta) : propAssignment;
  358. }
  359. } catch (e_7_1) {
  360. e_7 = {
  361. error: e_7_1
  362. };
  363. } finally {
  364. try {
  365. if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
  366. } finally {
  367. if (e_7) throw e_7.error;
  368. }
  369. }
  370. }
  371. return Object.assign({}, acc, partialUpdate);
  372. }, context) : context;
  373. return updatedContext;
  374. } // tslint:disable-next-line:no-empty
  375. exports.warn = function () {};
  376. if (!environment.IS_PRODUCTION) {
  377. exports.warn = function (condition, message) {
  378. var error = condition instanceof Error ? condition : undefined;
  379. if (!error && condition) {
  380. return;
  381. }
  382. if (console !== undefined) {
  383. var args = ["Warning: ".concat(message)];
  384. if (error) {
  385. args.push(error);
  386. } // tslint:disable-next-line:no-console
  387. console.warn.apply(console, args);
  388. }
  389. };
  390. }
  391. function isArray(value) {
  392. return Array.isArray(value);
  393. } // tslint:disable-next-line:ban-types
  394. function isFunction(value) {
  395. return typeof value === 'function';
  396. }
  397. function isString(value) {
  398. return typeof value === 'string';
  399. }
  400. function toGuard(condition, guardMap) {
  401. if (!condition) {
  402. return undefined;
  403. }
  404. if (isString(condition)) {
  405. return {
  406. type: constants.DEFAULT_GUARD_TYPE,
  407. name: condition,
  408. predicate: guardMap ? guardMap[condition] : undefined
  409. };
  410. }
  411. if (isFunction(condition)) {
  412. return {
  413. type: constants.DEFAULT_GUARD_TYPE,
  414. name: condition.name,
  415. predicate: condition
  416. };
  417. }
  418. return condition;
  419. }
  420. function isObservable(value) {
  421. try {
  422. return 'subscribe' in value && isFunction(value.subscribe);
  423. } catch (e) {
  424. return false;
  425. }
  426. }
  427. var symbolObservable = /*#__PURE__*/function () {
  428. return typeof Symbol === 'function' && Symbol.observable || '@@observable';
  429. }(); // TODO: to be removed in v5, left it out just to minimize the scope of the change and maintain compatibility with older versions of integration paackages
  430. var interopSymbols = (_a = {}, _a[symbolObservable] = function () {
  431. return this;
  432. }, _a[Symbol.observable] = function () {
  433. return this;
  434. }, _a);
  435. function isMachine(value) {
  436. return !!value && '__xstatenode' in value;
  437. }
  438. function isActor(value) {
  439. return !!value && typeof value.send === 'function';
  440. }
  441. var uniqueId = /*#__PURE__*/function () {
  442. var currentId = 0;
  443. return function () {
  444. currentId++;
  445. return currentId.toString(16);
  446. };
  447. }();
  448. function toEventObject(event, payload // id?: TEvent['type']
  449. ) {
  450. if (isString(event) || typeof event === 'number') {
  451. return _tslib.__assign({
  452. type: event
  453. }, payload);
  454. }
  455. return event;
  456. }
  457. function toSCXMLEvent(event, scxmlEvent) {
  458. if (!isString(event) && '$$type' in event && event.$$type === 'scxml') {
  459. return event;
  460. }
  461. var eventObject = toEventObject(event);
  462. return _tslib.__assign({
  463. name: eventObject.type,
  464. data: eventObject,
  465. $$type: 'scxml',
  466. type: 'external'
  467. }, scxmlEvent);
  468. }
  469. function toTransitionConfigArray(event, configLike) {
  470. var transitions = toArrayStrict(configLike).map(function (transitionLike) {
  471. if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string' || isMachine(transitionLike)) {
  472. return {
  473. target: transitionLike,
  474. event: event
  475. };
  476. }
  477. return _tslib.__assign(_tslib.__assign({}, transitionLike), {
  478. event: event
  479. });
  480. });
  481. return transitions;
  482. }
  483. function normalizeTarget(target) {
  484. if (target === undefined || target === constants.TARGETLESS_KEY) {
  485. return undefined;
  486. }
  487. return toArray(target);
  488. }
  489. function reportUnhandledExceptionOnInvocation(originalError, currentError, id) {
  490. if (!environment.IS_PRODUCTION) {
  491. var originalStackTrace = originalError.stack ? " Stacktrace was '".concat(originalError.stack, "'") : '';
  492. if (originalError === currentError) {
  493. // tslint:disable-next-line:no-console
  494. console.error("Missing onError handler for invocation '".concat(id, "', error was '").concat(originalError, "'.").concat(originalStackTrace));
  495. } else {
  496. var stackTrace = currentError.stack ? " Stacktrace was '".concat(currentError.stack, "'") : ''; // tslint:disable-next-line:no-console
  497. console.error("Missing onError handler and/or unhandled exception/promise rejection for invocation '".concat(id, "'. ") + "Original error: '".concat(originalError, "'. ").concat(originalStackTrace, " Current error is '").concat(currentError, "'.").concat(stackTrace));
  498. }
  499. }
  500. }
  501. function evaluateGuard(machine, guard, context, _event, state) {
  502. var guards = machine.options.guards;
  503. var guardMeta = {
  504. state: state,
  505. cond: guard,
  506. _event: _event
  507. }; // TODO: do not hardcode!
  508. if (guard.type === constants.DEFAULT_GUARD_TYPE) {
  509. return ((guards === null || guards === void 0 ? void 0 : guards[guard.name]) || guard.predicate)(context, _event.data, guardMeta);
  510. }
  511. var condFn = guards === null || guards === void 0 ? void 0 : guards[guard.type];
  512. if (!condFn) {
  513. throw new Error("Guard '".concat(guard.type, "' is not implemented on machine '").concat(machine.id, "'."));
  514. }
  515. return condFn(context, _event.data, guardMeta);
  516. }
  517. function toInvokeSource(src) {
  518. if (typeof src === 'string') {
  519. return {
  520. type: src
  521. };
  522. }
  523. return src;
  524. }
  525. function toObserver(nextHandler, errorHandler, completionHandler) {
  526. var noop = function () {};
  527. var isObserver = typeof nextHandler === 'object';
  528. var self = isObserver ? nextHandler : null;
  529. return {
  530. next: ((isObserver ? nextHandler.next : nextHandler) || noop).bind(self),
  531. error: ((isObserver ? nextHandler.error : errorHandler) || noop).bind(self),
  532. complete: ((isObserver ? nextHandler.complete : completionHandler) || noop).bind(self)
  533. };
  534. }
  535. function createInvokeId(stateNodeId, index) {
  536. return "".concat(stateNodeId, ":invocation[").concat(index, "]");
  537. }
  538. function isRaisableAction(action) {
  539. return (action.type === actionTypes.raise || action.type === actionTypes.send && action.to === types.SpecialTargets.Internal) && typeof action.delay !== 'number';
  540. }
  541. exports.createInvokeId = createInvokeId;
  542. exports.evaluateGuard = evaluateGuard;
  543. exports.flatten = flatten;
  544. exports.getActionType = getActionType;
  545. exports.getEventType = getEventType;
  546. exports.interopSymbols = interopSymbols;
  547. exports.isActor = isActor;
  548. exports.isArray = isArray;
  549. exports.isBehavior = isBehavior;
  550. exports.isBuiltInEvent = isBuiltInEvent;
  551. exports.isFunction = isFunction;
  552. exports.isMachine = isMachine;
  553. exports.isObservable = isObservable;
  554. exports.isPromiseLike = isPromiseLike;
  555. exports.isRaisableAction = isRaisableAction;
  556. exports.isStateLike = isStateLike;
  557. exports.isString = isString;
  558. exports.keys = keys;
  559. exports.mapContext = mapContext;
  560. exports.mapFilterValues = mapFilterValues;
  561. exports.mapValues = mapValues;
  562. exports.matchesState = matchesState;
  563. exports.nestedPath = nestedPath;
  564. exports.normalizeTarget = normalizeTarget;
  565. exports.partition = partition;
  566. exports.path = path;
  567. exports.pathToStateValue = pathToStateValue;
  568. exports.pathsToStateValue = pathsToStateValue;
  569. exports.reportUnhandledExceptionOnInvocation = reportUnhandledExceptionOnInvocation;
  570. exports.symbolObservable = symbolObservable;
  571. exports.toArray = toArray;
  572. exports.toArrayStrict = toArrayStrict;
  573. exports.toEventObject = toEventObject;
  574. exports.toGuard = toGuard;
  575. exports.toInvokeSource = toInvokeSource;
  576. exports.toObserver = toObserver;
  577. exports.toSCXMLEvent = toSCXMLEvent;
  578. exports.toStatePath = toStatePath;
  579. exports.toStatePaths = toStatePaths;
  580. exports.toStateValue = toStateValue;
  581. exports.toTransitionConfigArray = toTransitionConfigArray;
  582. exports.uniqueId = uniqueId;
  583. exports.updateContext = updateContext;
  584. exports.updateHistoryStates = updateHistoryStates;
  585. exports.updateHistoryValue = updateHistoryValue;