UNPKG

5.82 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.HookBuilder = void 0;
4var common_1 = require("../common/common");
5var predicates_1 = require("../common/predicates");
6var interface_1 = require("./interface");
7var transitionHook_1 = require("./transitionHook");
8/**
9 * This class returns applicable TransitionHooks for a specific Transition instance.
10 *
11 * Hooks ([[RegisteredHook]]) may be registered globally, e.g., $transitions.onEnter(...), or locally, e.g.
12 * myTransition.onEnter(...). The HookBuilder finds matching RegisteredHooks (where the match criteria is
13 * determined by the type of hook)
14 *
15 * The HookBuilder also converts RegisteredHooks objects to TransitionHook objects, which are used to run a Transition.
16 *
17 * The HookBuilder constructor is given the $transitions service and a Transition instance. Thus, a HookBuilder
18 * instance may only be used for one specific Transition object. (side note: the _treeChanges accessor is private
19 * in the Transition class, so we must also provide the Transition's _treeChanges)
20 */
21var HookBuilder = /** @class */ (function () {
22 function HookBuilder(transition) {
23 this.transition = transition;
24 }
25 HookBuilder.prototype.buildHooksForPhase = function (phase) {
26 var _this = this;
27 var $transitions = this.transition.router.transitionService;
28 return $transitions._pluginapi
29 ._getEvents(phase)
30 .map(function (type) { return _this.buildHooks(type); })
31 .reduce(common_1.unnestR, [])
32 .filter(common_1.identity);
33 };
34 /**
35 * Returns an array of newly built TransitionHook objects.
36 *
37 * - Finds all RegisteredHooks registered for the given `hookType` which matched the transition's [[TreeChanges]].
38 * - Finds [[PathNode]] (or `PathNode[]`) to use as the TransitionHook context(s)
39 * - For each of the [[PathNode]]s, creates a TransitionHook
40 *
41 * @param hookType the type of the hook registration function, e.g., 'onEnter', 'onFinish'.
42 */
43 HookBuilder.prototype.buildHooks = function (hookType) {
44 var transition = this.transition;
45 var treeChanges = transition.treeChanges();
46 // Find all the matching registered hooks for a given hook type
47 var matchingHooks = this.getMatchingHooks(hookType, treeChanges, transition);
48 if (!matchingHooks)
49 return [];
50 var baseHookOptions = {
51 transition: transition,
52 current: transition.options().current,
53 };
54 var makeTransitionHooks = function (hook) {
55 // Fetch the Nodes that caused this hook to match.
56 var matches = hook.matches(treeChanges, transition);
57 // Select the PathNode[] that will be used as TransitionHook context objects
58 var matchingNodes = matches[hookType.criteriaMatchPath.name];
59 // Return an array of HookTuples
60 return matchingNodes.map(function (node) {
61 var _options = common_1.extend({
62 bind: hook.bind,
63 traceData: { hookType: hookType.name, context: node },
64 }, baseHookOptions);
65 var state = hookType.criteriaMatchPath.scope === interface_1.TransitionHookScope.STATE ? node.state.self : null;
66 var transitionHook = new transitionHook_1.TransitionHook(transition, state, hook, _options);
67 return { hook: hook, node: node, transitionHook: transitionHook };
68 });
69 };
70 return matchingHooks
71 .map(makeTransitionHooks)
72 .reduce(common_1.unnestR, [])
73 .sort(tupleSort(hookType.reverseSort))
74 .map(function (tuple) { return tuple.transitionHook; });
75 };
76 /**
77 * Finds all RegisteredHooks from:
78 * - The Transition object instance hook registry
79 * - The TransitionService ($transitions) global hook registry
80 *
81 * which matched:
82 * - the eventType
83 * - the matchCriteria (to, from, exiting, retained, entering)
84 *
85 * @returns an array of matched [[RegisteredHook]]s
86 */
87 HookBuilder.prototype.getMatchingHooks = function (hookType, treeChanges, transition) {
88 var isCreate = hookType.hookPhase === interface_1.TransitionHookPhase.CREATE;
89 // Instance and Global hook registries
90 var $transitions = this.transition.router.transitionService;
91 var registries = isCreate ? [$transitions] : [this.transition, $transitions];
92 return registries
93 .map(function (reg) { return reg.getHooks(hookType.name); }) // Get named hooks from registries
94 .filter(common_1.assertPredicate(predicates_1.isArray, "broken event named: " + hookType.name)) // Sanity check
95 .reduce(common_1.unnestR, []) // Un-nest RegisteredHook[][] to RegisteredHook[] array
96 .filter(function (hook) { return hook.matches(treeChanges, transition); }); // Only those satisfying matchCriteria
97 };
98 return HookBuilder;
99}());
100exports.HookBuilder = HookBuilder;
101/**
102 * A factory for a sort function for HookTuples.
103 *
104 * The sort function first compares the PathNode depth (how deep in the state tree a node is), then compares
105 * the EventHook priority.
106 *
107 * @param reverseDepthSort a boolean, when true, reverses the sort order for the node depth
108 * @returns a tuple sort function
109 */
110function tupleSort(reverseDepthSort) {
111 if (reverseDepthSort === void 0) { reverseDepthSort = false; }
112 return function nodeDepthThenPriority(l, r) {
113 var factor = reverseDepthSort ? -1 : 1;
114 var depthDelta = (l.node.state.path.length - r.node.state.path.length) * factor;
115 return depthDelta !== 0 ? depthDelta : r.hook.priority - l.hook.priority;
116 };
117}
118//# sourceMappingURL=hookBuilder.js.map
\No newline at end of file