navigation-stack 0.3.1 → 0.5.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.
Files changed (257) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +611 -163
  3. package/data-storage/package.json +6 -0
  4. package/karma.conf.cjs +21 -4
  5. package/lib/cjs/NavigationStack.js +88 -0
  6. package/lib/cjs/data-storage/DataStorage.js +71 -0
  7. package/lib/cjs/data-storage/LocationDataStorage.js +29 -0
  8. package/lib/cjs/data-storage/index.js +9 -0
  9. package/lib/cjs/debug.js +12 -0
  10. package/lib/cjs/environment/InMemoryEnvironment.js +15 -0
  11. package/lib/cjs/environment/WebBrowserEnvironment.js +15 -0
  12. package/lib/cjs/environment/data-storage/InMemoryDataStorage.js +27 -0
  13. package/lib/cjs/environment/data-storage/WebBrowserDataStorage.js +21 -0
  14. package/lib/cjs/environment/scroll-position/InMemoryScrollPosition.js +44 -0
  15. package/lib/cjs/environment/scroll-position/WebBrowserScrollPosition.js +60 -0
  16. package/lib/cjs/getLocationFromInternalLocation.js +14 -0
  17. package/lib/cjs/index.js +20 -16
  18. package/lib/cjs/navigationBlockers.js +28 -23
  19. package/lib/cjs/{normalizeInputLocation.js → parseInputLocation.js} +25 -9
  20. package/lib/cjs/{ActionTypes.js → redux/ActionTypes.js} +1 -1
  21. package/lib/cjs/redux/ActionTypesInternal.js +8 -0
  22. package/lib/cjs/{Actions.js → redux/Actions.js} +5 -4
  23. package/lib/cjs/redux/createMiddlewares.js +60 -0
  24. package/lib/cjs/redux/index.js +13 -0
  25. package/lib/cjs/redux/internalLocationReducer.js +14 -0
  26. package/lib/cjs/redux/middleware/createAddInputLocationBasePathMiddleware.js +32 -0
  27. package/lib/cjs/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +113 -0
  28. package/lib/cjs/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +94 -0
  29. package/lib/cjs/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +30 -0
  30. package/lib/cjs/redux/middleware/createUpdateInternalLocationMiddleware.js +73 -0
  31. package/lib/cjs/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +11 -8
  32. package/lib/cjs/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +6 -4
  33. package/lib/cjs/redux/middleware/updateLocationMiddleware.js +34 -0
  34. package/lib/cjs/scroll-position/PageScrollPositionSetter.js +97 -0
  35. package/lib/cjs/scroll-position/ScrollPositionAutoSaver.js +141 -0
  36. package/lib/cjs/scroll-position/ScrollPositionRestoration.js +407 -0
  37. package/lib/cjs/scroll-position/ScrollPositionSaver.js +87 -0
  38. package/lib/cjs/scroll-position/ScrollPositionSetter.js +16 -0
  39. package/lib/cjs/scroll-position/constants.js +5 -0
  40. package/lib/cjs/scroll-position/index.js +7 -0
  41. package/lib/cjs/scroll-position/scheduleNextTick.js +11 -0
  42. package/lib/cjs/session/InMemorySession.js +22 -0
  43. package/lib/cjs/session/ServerSideRenderSession.js +17 -0
  44. package/lib/cjs/session/Session.js +202 -0
  45. package/lib/cjs/session/WebBrowserSession.js +20 -0
  46. package/lib/cjs/session/key/createSessionKey.js +23 -0
  47. package/lib/cjs/session/lifecycle/InMemorySessionLifecycle.js +19 -0
  48. package/lib/cjs/session/lifecycle/WebBrowserSessionLifecycle.js +128 -0
  49. package/lib/cjs/session/lifecycle/page-lifecycle/PageLifecycle.js +269 -0
  50. package/lib/cjs/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +8 -0
  51. package/lib/cjs/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +33 -0
  52. package/lib/cjs/session/navigation/InMemoryNavigation.js +104 -0
  53. package/lib/cjs/session/navigation/ServerSideNavigation.js +61 -0
  54. package/lib/cjs/session/navigation/WebBrowserNavigation.js +221 -0
  55. package/lib/cjs/session/navigation/error/NavigationOutOfBoundsError.js +12 -0
  56. package/lib/cjs/session/navigation/error/ServerSideNavigationError.js +21 -0
  57. package/lib/cjs/session/navigation/operation/operations.js +11 -0
  58. package/lib/cjs/session/subscription/Subscription.js +81 -0
  59. package/lib/data-storage/index.d.ts +35 -0
  60. package/lib/esm/NavigationStack.js +81 -0
  61. package/lib/esm/data-storage/DataStorage.js +65 -0
  62. package/lib/esm/data-storage/LocationDataStorage.js +22 -0
  63. package/lib/esm/data-storage/index.js +2 -0
  64. package/lib/esm/debug.js +7 -0
  65. package/lib/esm/environment/InMemoryEnvironment.js +8 -0
  66. package/lib/esm/environment/WebBrowserEnvironment.js +8 -0
  67. package/lib/esm/environment/data-storage/InMemoryDataStorage.js +21 -0
  68. package/lib/esm/environment/data-storage/WebBrowserDataStorage.js +15 -0
  69. package/lib/esm/environment/scroll-position/InMemoryScrollPosition.js +38 -0
  70. package/lib/esm/environment/scroll-position/WebBrowserScrollPosition.js +54 -0
  71. package/lib/esm/getLocationFromInternalLocation.js +9 -0
  72. package/lib/esm/index.js +10 -8
  73. package/lib/esm/navigationBlockers.js +28 -23
  74. package/lib/esm/{normalizeInputLocation.js → parseInputLocation.js} +24 -8
  75. package/lib/esm/{ActionTypes.js → redux/ActionTypes.js} +1 -1
  76. package/lib/esm/redux/ActionTypesInternal.js +3 -0
  77. package/lib/esm/{Actions.js → redux/Actions.js} +5 -4
  78. package/lib/esm/redux/createMiddlewares.js +54 -0
  79. package/lib/esm/redux/index.js +4 -0
  80. package/lib/esm/redux/internalLocationReducer.js +8 -0
  81. package/lib/esm/redux/middleware/createAddInputLocationBasePathMiddleware.js +27 -0
  82. package/lib/esm/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +108 -0
  83. package/lib/esm/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +88 -0
  84. package/lib/esm/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +25 -0
  85. package/lib/esm/redux/middleware/createUpdateInternalLocationMiddleware.js +68 -0
  86. package/lib/esm/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +10 -7
  87. package/lib/esm/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +5 -3
  88. package/lib/esm/redux/middleware/updateLocationMiddleware.js +28 -0
  89. package/lib/esm/scroll-position/PageScrollPositionSetter.js +91 -0
  90. package/lib/esm/scroll-position/ScrollPositionAutoSaver.js +134 -0
  91. package/lib/esm/scroll-position/ScrollPositionRestoration.js +400 -0
  92. package/lib/esm/scroll-position/ScrollPositionSaver.js +80 -0
  93. package/lib/esm/scroll-position/ScrollPositionSetter.js +10 -0
  94. package/lib/esm/scroll-position/constants.js +1 -0
  95. package/lib/esm/scroll-position/index.js +1 -0
  96. package/lib/esm/scroll-position/scheduleNextTick.js +6 -0
  97. package/lib/esm/session/InMemorySession.js +15 -0
  98. package/lib/esm/session/ServerSideRenderSession.js +11 -0
  99. package/lib/esm/session/Session.js +195 -0
  100. package/lib/esm/session/WebBrowserSession.js +13 -0
  101. package/lib/esm/session/key/createSessionKey.js +18 -0
  102. package/lib/esm/session/lifecycle/InMemorySessionLifecycle.js +13 -0
  103. package/lib/esm/session/lifecycle/WebBrowserSessionLifecycle.js +120 -0
  104. package/lib/esm/session/lifecycle/page-lifecycle/PageLifecycle.js +263 -0
  105. package/lib/esm/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +2 -0
  106. package/lib/esm/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +30 -0
  107. package/lib/esm/session/navigation/InMemoryNavigation.js +97 -0
  108. package/lib/esm/session/navigation/ServerSideNavigation.js +54 -0
  109. package/lib/esm/session/navigation/WebBrowserNavigation.js +213 -0
  110. package/lib/esm/session/navigation/error/NavigationOutOfBoundsError.js +6 -0
  111. package/lib/esm/session/navigation/error/ServerSideNavigationError.js +14 -0
  112. package/lib/esm/session/navigation/operation/operations.js +6 -0
  113. package/lib/esm/session/subscription/Subscription.js +75 -0
  114. package/lib/index.d.ts +179 -157
  115. package/lib/redux/index.d.ts +90 -0
  116. package/lib/scroll-position/index.d.ts +107 -0
  117. package/package.json +9 -5
  118. package/redux/package.json +6 -0
  119. package/scroll-position/package.json +6 -0
  120. package/src/NavigationStack.js +100 -0
  121. package/src/data-storage/DataStorage.js +69 -0
  122. package/src/data-storage/LocationDataStorage.js +23 -0
  123. package/src/data-storage/index.js +2 -0
  124. package/src/debug.js +8 -0
  125. package/src/environment/InMemoryEnvironment.js +9 -0
  126. package/src/environment/WebBrowserEnvironment.js +9 -0
  127. package/src/environment/data-storage/InMemoryDataStorage.js +23 -0
  128. package/src/environment/data-storage/WebBrowserDataStorage.js +17 -0
  129. package/src/environment/scroll-position/InMemoryScrollPosition.js +45 -0
  130. package/src/environment/scroll-position/WebBrowserScrollPosition.js +72 -0
  131. package/src/getLocationFromInternalLocation.js +7 -0
  132. package/src/index.js +10 -8
  133. package/src/navigationBlockers.js +31 -27
  134. package/src/{normalizeInputLocation.js → parseInputLocation.js} +23 -8
  135. package/src/{ActionTypes.js → redux/ActionTypes.js} +1 -1
  136. package/src/redux/ActionTypesInternal.js +3 -0
  137. package/src/{Actions.js → redux/Actions.js} +4 -3
  138. package/src/redux/createMiddlewares.js +65 -0
  139. package/src/redux/index.js +4 -0
  140. package/src/redux/internalLocationReducer.js +9 -0
  141. package/src/redux/middleware/createAddInputLocationBasePathMiddleware.js +27 -0
  142. package/src/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +119 -0
  143. package/src/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +94 -0
  144. package/src/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +26 -0
  145. package/src/redux/middleware/createUpdateInternalLocationMiddleware.js +72 -0
  146. package/src/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +10 -3
  147. package/src/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +5 -3
  148. package/src/redux/middleware/updateLocationMiddleware.js +28 -0
  149. package/src/scroll-position/PageScrollPositionSetter.js +110 -0
  150. package/src/scroll-position/ScrollPositionAutoSaver.js +168 -0
  151. package/src/scroll-position/ScrollPositionRestoration.js +551 -0
  152. package/src/scroll-position/ScrollPositionSaver.js +120 -0
  153. package/src/scroll-position/ScrollPositionSetter.js +16 -0
  154. package/src/scroll-position/constants.js +1 -0
  155. package/src/scroll-position/index.js +1 -0
  156. package/src/scroll-position/scheduleNextTick.js +6 -0
  157. package/src/session/InMemorySession.js +13 -0
  158. package/src/session/ServerSideRenderSession.js +9 -0
  159. package/src/session/Session.js +238 -0
  160. package/src/session/WebBrowserSession.js +13 -0
  161. package/src/session/key/createSessionKey.js +18 -0
  162. package/src/session/lifecycle/InMemorySessionLifecycle.js +13 -0
  163. package/src/session/lifecycle/WebBrowserSessionLifecycle.js +126 -0
  164. package/src/session/lifecycle/page-lifecycle/PageLifecycle.js +291 -0
  165. package/src/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +3 -0
  166. package/src/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +32 -0
  167. package/src/session/navigation/InMemoryNavigation.js +78 -0
  168. package/src/session/navigation/ServerSideNavigation.js +43 -0
  169. package/src/session/navigation/WebBrowserNavigation.js +224 -0
  170. package/src/session/navigation/error/NavigationOutOfBoundsError.js +7 -0
  171. package/src/session/navigation/error/ServerSideNavigationError.js +18 -0
  172. package/src/session/navigation/operation/operations.js +6 -0
  173. package/src/session/subscription/Subscription.js +76 -0
  174. package/test/NavigationStack.test.js +296 -0
  175. package/test/{LocationDataStorage.test.js → data-storage/LocationDataStorage.test.js} +3 -3
  176. package/test/data-storage/index.test.js +8 -0
  177. package/test/index.js +12 -0
  178. package/test/index.test.js +8 -7
  179. package/test/{helpers.js → middlewareTestUtil.js} +9 -12
  180. package/test/{normalizeInputLocation.test.js → parseInputLocationMiddleware.test.js} +9 -9
  181. package/test/{Action.test.js → redux/Action.test.js} +7 -6
  182. package/test/{ActionTypes.test.js → redux/ActionTypes.test.js} +2 -2
  183. package/test/redux/createMiddlewares.test.js +96 -0
  184. package/test/redux/index.test.js +10 -0
  185. package/test/{locationReducer.test.js → redux/locationReducer.test.js} +4 -7
  186. package/test/redux/middleware/createAddInputLocationBasePathMiddleware.test.js +40 -0
  187. package/test/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.test.js +264 -0
  188. package/test/redux/middleware/createProgrammaticNavigationBlockerMiddleware.test.js +312 -0
  189. package/test/redux/middleware/createRemoveOutputLocationBasePathMiddleware.test.js +51 -0
  190. package/test/{middleware/navigationActionMiddleware.test.js → redux/middleware/navigationOperationMiddleware.test.js} +16 -12
  191. package/test/{middleware/normalizeInputLocationMiddleware.test.js → redux/middleware/parseInputLocationMiddleware.test.js} +4 -4
  192. package/test/scroll-position/ScrollPositionRestoration.test.js +435 -0
  193. package/test/scroll-position/addScrollableContainer.js +39 -0
  194. package/test/scroll-position/addScrollableContainerWithAnchors.js +56 -0
  195. package/test/scroll-position/createApp.js +132 -0
  196. package/test/scroll-position/delay.js +9 -0
  197. package/test/scroll-position/mockPageLifecycle.js +17 -0
  198. package/test/scroll-position/runApp.js +24 -0
  199. package/test/scroll-position/withScrollableContainerAtIndexPageWithDisabledAutomaticScrollPositionRestoration.js +72 -0
  200. package/test/session/InMemorySession.test.js +348 -0
  201. package/test/session/ServerSession.test.js +17 -9
  202. package/test/session/WebBrowserSession.test.js +265 -0
  203. package/test/testUtil.js +3 -0
  204. package/types/data-storage/index.d.ts +35 -0
  205. package/types/index.d.ts +179 -157
  206. package/types/redux/index.d.ts +90 -0
  207. package/types/scroll-position/index.d.ts +107 -0
  208. package/types/tsconfig.json +1 -1
  209. package/lib/cjs/LocationDataStorage.js +0 -61
  210. package/lib/cjs/addBeforeLocationChangeListener.js +0 -7
  211. package/lib/cjs/beforeLocationChangeListeners.js +0 -51
  212. package/lib/cjs/createMiddlewares.js +0 -47
  213. package/lib/cjs/middleware/createBasePathMiddleware.js +0 -24
  214. package/lib/cjs/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -39
  215. package/lib/cjs/middleware/createLocationMiddleware.js +0 -56
  216. package/lib/cjs/middleware/createNavigationBlockerMiddleware.js +0 -161
  217. package/lib/cjs/middleware/createTransformLocationMiddleware.js +0 -38
  218. package/lib/cjs/onlyAllowedOnClientSide.js +0 -10
  219. package/lib/cjs/session/BrowserSession.js +0 -235
  220. package/lib/cjs/session/MemorySession.js +0 -223
  221. package/lib/cjs/session/ServerSession.js +0 -65
  222. package/lib/esm/LocationDataStorage.js +0 -54
  223. package/lib/esm/addBeforeLocationChangeListener.js +0 -2
  224. package/lib/esm/beforeLocationChangeListeners.js +0 -44
  225. package/lib/esm/createMiddlewares.js +0 -41
  226. package/lib/esm/middleware/createBasePathMiddleware.js +0 -19
  227. package/lib/esm/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -34
  228. package/lib/esm/middleware/createLocationMiddleware.js +0 -50
  229. package/lib/esm/middleware/createNavigationBlockerMiddleware.js +0 -156
  230. package/lib/esm/middleware/createTransformLocationMiddleware.js +0 -33
  231. package/lib/esm/onlyAllowedOnClientSide.js +0 -5
  232. package/lib/esm/session/BrowserSession.js +0 -229
  233. package/lib/esm/session/MemorySession.js +0 -217
  234. package/lib/esm/session/ServerSession.js +0 -58
  235. package/src/LocationDataStorage.js +0 -60
  236. package/src/addBeforeLocationChangeListener.js +0 -2
  237. package/src/beforeLocationChangeListeners.js +0 -54
  238. package/src/createMiddlewares.js +0 -45
  239. package/src/middleware/createBasePathMiddleware.js +0 -20
  240. package/src/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -40
  241. package/src/middleware/createLocationMiddleware.js +0 -55
  242. package/src/middleware/createNavigationBlockerMiddleware.js +0 -168
  243. package/src/middleware/createTransformLocationMiddleware.js +0 -29
  244. package/src/onlyAllowedOnClientSide.js +0 -5
  245. package/src/session/BrowserSession.js +0 -235
  246. package/src/session/MemorySession.js +0 -219
  247. package/src/session/ServerSession.js +0 -67
  248. package/test/createMiddlewares.test.js +0 -62
  249. package/test/middleware/createBasePathMiddleware.test.js +0 -67
  250. package/test/middleware/createBeforeLocationChangeListenerMiddleware.test.js +0 -141
  251. package/test/middleware/createNavigationBlockerMiddleware.test.js +0 -471
  252. package/test/middleware/createTransformLocationMiddleware.test.js +0 -44
  253. package/test/session/BrowserSession.test.js +0 -182
  254. package/test/session/MemorySession.test.js +0 -244
  255. /package/lib/cjs/{locationReducer.js → redux/locationReducer.js} +0 -0
  256. /package/lib/esm/{locationReducer.js → redux/locationReducer.js} +0 -0
  257. /package/src/{locationReducer.js → redux/locationReducer.js} +0 -0
@@ -1,61 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = void 0;
5
- var _getLocationUrl = _interopRequireDefault(require("./getLocationUrl"));
6
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
- class LocationDataStorage {
8
- constructor(environment, {
9
- namespace
10
- }) {
11
- this._environment = environment;
12
- this._getFallbackLocationKey = _getLocationUrl.default;
13
- this._stateKeyPrefix = `${namespace}|`;
14
- // this._stateKeyPrefix = namespace ? `${namespace}|` : '';
15
- }
16
- get(location, key) {
17
- const stateKey = this._getStateKey(location, key);
18
- try {
19
- const value = this._environment.dataStorage.get(stateKey);
20
- // === null is probably sufficient.
21
- if (value === null) {
22
- return undefined;
23
- }
24
-
25
- // We want to catch JSON parse errors in case someone separately threw
26
- // junk into sessionStorage under our namespace.
27
- return JSON.parse(value);
28
- } catch (error) {
29
- // Pretend that the entry doesn't exist.
30
- return undefined;
31
- }
32
- }
33
- set(location, key, value) {
34
- const stateKey = this._getStateKey(location, key);
35
- if (value === undefined) {
36
- try {
37
- this._environment.dataStorage.remove(stateKey);
38
- } catch (error) {
39
- // No need to handle errors here.
40
- }
41
- return;
42
- }
43
-
44
- // Unlike with read, we want to fail on invalid values here, since the
45
- // value here is provided by the caller of this method.
46
- const valueString = JSON.stringify(value);
47
- try {
48
- this._environment.dataStorage.set(stateKey, valueString);
49
- } catch (error) {
50
- // No need to handle errors here either. If it didn't work, it didn't
51
- // work. We make no guarantees about actually saving the value.
52
- }
53
- }
54
- _getStateKey(location, key) {
55
- const locationKey = location.key || this._getFallbackLocationKey(location);
56
- const keyPrefix = `${this._stateKeyPrefix}${locationKey}`;
57
- return `${keyPrefix}|${key}`;
58
- }
59
- }
60
- exports.default = LocationDataStorage;
61
- module.exports = exports.default;
@@ -1,7 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = void 0;
5
- var _beforeLocationChangeListeners = require("./beforeLocationChangeListeners");
6
- exports.default = _beforeLocationChangeListeners.addBeforeLocationChangeListener;
7
- module.exports = exports.default;
@@ -1,51 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.addBeforeLocationChangeListener = addBeforeLocationChangeListener;
5
- exports.getBeforeLocationChangeListeners = getBeforeLocationChangeListeners;
6
- exports.removeAllBeforeLocationChangeListeners = removeAllBeforeLocationChangeListeners;
7
- exports.runBeforeLocationChangeListeners = runBeforeLocationChangeListeners;
8
- /* eslint-disable no-underscore-dangle */
9
-
10
- function getBeforeLocationChangeListeners(session) {
11
- return session._beforeLocationChangeListenersList || [];
12
- }
13
- function addBeforeLocationChangeListenerToTheList(listener, session) {
14
- if (!session._beforeLocationChangeListenersList) {
15
- session._beforeLocationChangeListenersList = [];
16
- }
17
- session._beforeLocationChangeListenersList.push(listener);
18
- }
19
- function removeBeforeLocationChangeListenerFromTheList(listener, session) {
20
- if (session._beforeLocationChangeListenersList) {
21
- session._beforeLocationChangeListenersList = session._beforeLocationChangeListenersList.filter(_ => _ !== listener);
22
- }
23
- }
24
- function removeAllBeforeLocationChangeListeners(session) {
25
- session._beforeLocationChangeListenersList = [];
26
- }
27
-
28
- // Runs the `listener` while ignoring any errors that might be thrown by it.
29
- function runBeforeLocationChangeListener(listener, location) {
30
- try {
31
- listener(location);
32
- } catch (error) {
33
- // eslint-disable-next-line no-console
34
- console.warn(`Ignoring before location change listener \`${listener.name}\` that failed with \`${error}\`.`);
35
- // eslint-disable-next-line no-console
36
- console.error(error);
37
- }
38
- }
39
-
40
- // Runs all listeners in order.
41
- function runBeforeLocationChangeListeners(navigationListeners, toLocation) {
42
- for (const listener of navigationListeners) {
43
- runBeforeLocationChangeListener(listener, toLocation);
44
- }
45
- }
46
- function addBeforeLocationChangeListener(session, listener) {
47
- addBeforeLocationChangeListenerToTheList(listener, session);
48
- return () => {
49
- removeBeforeLocationChangeListenerFromTheList(listener, session);
50
- };
51
- }
@@ -1,47 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = createMiddlewares;
5
- var _createBasePathMiddleware = _interopRequireDefault(require("./middleware/createBasePathMiddleware"));
6
- var _createBeforeLocationChangeListenerMiddleware = _interopRequireDefault(require("./middleware/createBeforeLocationChangeListenerMiddleware"));
7
- var _createLocationMiddleware = _interopRequireDefault(require("./middleware/createLocationMiddleware"));
8
- var _createNavigationBlockerMiddleware = _interopRequireDefault(require("./middleware/createNavigationBlockerMiddleware"));
9
- var _navigationActionMiddleware = _interopRequireDefault(require("./middleware/navigationActionMiddleware"));
10
- var _normalizeInputLocationMiddleware = _interopRequireDefault(require("./middleware/normalizeInputLocationMiddleware"));
11
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
- function createMiddlewares(session, options) {
13
- // Allows temporarily ignoring location update events.
14
- let shouldIgnoreLocationSubscriptionEvents = false;
15
- const ignoreLocationSubscriptionEvents = func => {
16
- shouldIgnoreLocationSubscriptionEvents = true;
17
- func();
18
- shouldIgnoreLocationSubscriptionEvents = false;
19
- };
20
- return [
21
- // Validates that the action "payload" (input location) is a proper `NormalizedInputLocation`.
22
- _normalizeInputLocationMiddleware.default,
23
- // Transforms a "PUSH" / "REPLACE" action into a "NAVIGATE" action.
24
- _navigationActionMiddleware.default,
25
- // If a website is hosted under a certain path (`basePath`)
26
- // then this middleware will automatically strip that starting segment from the `pathname` of `location`s.
27
- (0, _createBasePathMiddleware.default)(options && options.basePath),
28
- // Allows blocking navigation.
29
- // Handles `NAVIGATE` actions dispatched by the application itself.
30
- (0, _createNavigationBlockerMiddleware.default)(session, {
31
- ignoreLocationSubscriptionEvents
32
- }),
33
- // This "middleware" performs the actual navigation according to the `session` being used.
34
- // For example, when `BrowserSession` is used, it calls methods of the `history` object.
35
- (0, _createLocationMiddleware.default)(session, {
36
- shouldIgnoreLocationSubscriptionEvents: () => shouldIgnoreLocationSubscriptionEvents
37
- }),
38
- // Allows blocking navigation.
39
- // Handles location `UPDATE` actions dispatched in response to location update events.
40
- (0, _createNavigationBlockerMiddleware.default)(session, {
41
- ignoreLocationSubscriptionEvents
42
- }),
43
- // Allows subscribing to upcoming location changes
44
- // before those changes are applied in the `location` object in the state.
45
- (0, _createBeforeLocationChangeListenerMiddleware.default)(session)];
46
- }
47
- module.exports = exports.default;
@@ -1,24 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = createBasePathMiddleware;
5
- var _basePath = require("../basePath");
6
- var _createTransformLocationMiddleware = _interopRequireDefault(require("./createTransformLocationMiddleware"));
7
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
- // Creates a "middleware" that, when a website is hosted under a certain path (`basePath`),
9
- // automatically strips that starting segment from the `pathname` of `location`s.
10
- function createBasePathMiddleware(basePath) {
11
- return (0, _createTransformLocationMiddleware.default)({
12
- // Transforms input `Location`:
13
- // prepends `basePath` to the URL.
14
- transformInputLocation: location => {
15
- return (0, _basePath.addBasePath)(location, basePath);
16
- },
17
- // Transforms subscription `Location` object:
18
- // removes `basePath` from the URL.
19
- transformSubscriptionLocation: location => {
20
- return (0, _basePath.removeBasePath)(location, basePath);
21
- }
22
- });
23
- }
24
- module.exports = exports.default;
@@ -1,39 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = createBeforeLocationChangeListenerMiddleware;
5
- var _ActionTypes = _interopRequireDefault(require("../ActionTypes"));
6
- var _beforeLocationChangeListeners = require("../beforeLocationChangeListeners");
7
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
- // Creates a "middleware" that calls upcoming navigation listeners.
9
- function createBeforeLocationChangeListenerMiddleware(session) {
10
- return function navigationListenerMiddleware() {
11
- return next => action => {
12
- const {
13
- type,
14
- payload
15
- } = action;
16
- switch (type) {
17
- // Trigger navigation listeners before the `location` has been updated in Redux state.
18
- // It doesn't matter that the new location URL has already been updated in the web browser's
19
- // address bar, or that the web browser's history has already switched to the new locaiton.
20
- // From the application's point of view, all of that doesn't matter and even doesn't exist.
21
- // All that exists from the application's point of view is the `location` object in the Redux state.
22
- // Until the `location` object in the Redux state is updated, the old page is still rendered.
23
- // The appliation is only concerned with the updates of the `location` object in the Redux state
24
- // and completely ignores any updates to the URL in the web browser's address bar.
25
- case _ActionTypes.default.UPDATE:
26
- (0, _beforeLocationChangeListeners.runBeforeLocationChangeListeners)((0, _beforeLocationChangeListeners.getBeforeLocationChangeListeners)(session), payload);
27
- return next(action);
28
-
29
- // Remove any navigation listeners on `DISPOSE` event.
30
- case _ActionTypes.default.DISPOSE:
31
- (0, _beforeLocationChangeListeners.removeAllBeforeLocationChangeListeners)(session);
32
- return next(action);
33
- default:
34
- return next(action);
35
- }
36
- };
37
- };
38
- }
39
- module.exports = exports.default;
@@ -1,56 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = createLocationMiddleware;
5
- var _ActionTypes = _interopRequireDefault(require("../ActionTypes"));
6
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
- function updateLocation(location) {
8
- return {
9
- type: _ActionTypes.default.UPDATE,
10
- payload: location
11
- };
12
- }
13
-
14
- // Creates a "middleware" that performs the actual navigation according to the `session` being used.
15
- // For example, when `BrowserSession` is used, it calls methods of the `window.history` object.
16
- function createLocationMiddleware(session, {
17
- shouldIgnoreLocationSubscriptionEvents
18
- }) {
19
- return function locationMiddleware() {
20
- return next => {
21
- // Whenever browser location changes,
22
- // perform the same changes with the internal `location` object.
23
- const unsubscribe = session.navigation.subscribe(location => {
24
- if (!shouldIgnoreLocationSubscriptionEvents()) {
25
- next(updateLocation(location));
26
- }
27
- });
28
- return action => {
29
- const {
30
- type,
31
- payload
32
- } = action;
33
- switch (type) {
34
- case _ActionTypes.default.INIT:
35
- return next(updateLocation(session.navigation.init()));
36
- case _ActionTypes.default.NAVIGATE:
37
- // `session.navigate()` doesn't trigger the `subscribe()` listener.
38
- return next(updateLocation(session.navigation.navigate(payload)));
39
- case _ActionTypes.default.SHIFT:
40
- // `shift()` will trigger the `subscribe()` listener,
41
- // which will call `updateLocation()`.
42
- session.navigation.shift(payload);
43
- // eslint-disable-next-line consistent-return
44
- return;
45
- case _ActionTypes.default.DISPOSE:
46
- unsubscribe();
47
- // eslint-disable-next-line consistent-return
48
- return;
49
- default:
50
- return next(action);
51
- }
52
- };
53
- };
54
- };
55
- }
56
- module.exports = exports.default;
@@ -1,161 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = createNavigationBlockerMiddleware;
5
- var _ActionTypes = _interopRequireDefault(require("../ActionTypes"));
6
- var _isPromise = _interopRequireDefault(require("../isPromise"));
7
- var _navigationBlockers = require("../navigationBlockers");
8
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
- // Creates a "middleware" that applies navigation blockers.
10
- function createNavigationBlockerMiddleware(session, {
11
- ignoreLocationSubscriptionEvents
12
- }) {
13
- function createNavigationBlockersEvaluationStatus() {
14
- /* eslint-disable no-underscore-dangle */
15
- if (session._navigationBlockersEvaluationStatus) {
16
- session._navigationBlockersEvaluationStatus.cancelled = true;
17
- }
18
- session._navigationBlockersEvaluationStatus = {
19
- cancelled: false
20
- };
21
- return session._navigationBlockersEvaluationStatus;
22
- }
23
- return function navigationBlockerMiddleware() {
24
- return next => action => {
25
- const {
26
- type,
27
- payload
28
- } = action;
29
-
30
- // Declaring `result` variable here fixes ESLint error:
31
- // "Unexpected lexical declaration in case block".
32
- let result;
33
- switch (type) {
34
- // Prevent or allow navigation that was initiated by the application
35
- // by dispatching a `.push()` or `.replace()` action.
36
- //
37
- // It doesn't handle `.shift()` navigation actions because it doesn't yet know
38
- // the `location` that it's gonna `shift` to. Instead, it waits for the web browser
39
- // to "shift" to that `location` and then reads it and rewinds the "shift"
40
- // if it should've been blocked. That is handled in the `case ActionTypes.UPDATE` block.
41
- //
42
- // This type of "shifting" and then rewinding the "shift" doesn't really matter to the application at all.
43
- // From the application's point of view, all of that doesn't matter and even doesn't exist.
44
- // All that exists from the application's point of view is the `location` object in the Redux state.
45
- // Until the `location` object in the Redux state is updated, the old page is still rendered.
46
- // The appliation is only concerned with the updates of the `location` object in the Redux state
47
- // and completely ignores any updates to the URL in the web browser's address bar.
48
- //
49
- case _ActionTypes.default.NAVIGATE:
50
- // `resultValue` variable name works around a stupid javascript error:
51
- // "Cannot redeclare block-scoped variable 'result'".
52
- result = (0, _navigationBlockers.runNavigationBlockers)((0, _navigationBlockers.getNavigationBlockers)(session), payload);
53
- if ((0, _isPromise.default)(result)) {
54
- const status = createNavigationBlockersEvaluationStatus();
55
- // eslint-disable-next-line consistent-return
56
- result.then(resultValue => {
57
- if (!status.cancelled) {
58
- if (!resultValue) {
59
- return next(action);
60
- }
61
- }
62
- });
63
- } else if (!result) {
64
- return next(action);
65
- }
66
- // eslint-disable-next-line consistent-return
67
- return;
68
-
69
- // One can notice that this "middleware" handles both `NAVIGATE` and `UPDATE` Redux actions,
70
- // even though a `NAVIGATE` action normally always causes a follow-up `UPDATE` Redux action.
71
- // There's no contradiction here: if a navigation blocker should block a certain navigation,
72
- // it will do that at the `NAVIGATION` stage and it won't get to the `UPDATE` stage, so it
73
- // won't be called "second time" or something like that.
74
- //
75
- // One could ask then: Why handle `UPDATE` Redux action at all?
76
- // The reason why it handles `UPDATE` Redux actions here is because
77
- // `NAVIGATE` Redux actions are only emitted for programmatic "push" or "replace" navigation
78
- // initiated by the application code, and there're other cases of navigation such as
79
- // programmatic "shift" navigation or when the user manually clicks "Back" or "Forward" button
80
- // in a web browser. Such "other" cases could only be handled by reacting to an `UPDATE` Redux action
81
- // which is only emitted after the URL in the browser's address bar has changed.
82
- //
83
- // But there's no real drawback in reacting to an `UPDATE` Redux action "post factum" because
84
- // from the application's point of view the address bar doesn't matter and even doesn't exist.
85
- // All that exists from the application's point of view is the `location` object in the Redux state.
86
- // Until the `location` object in the Redux state is updated, the old page is still rendered.
87
- // The appliation is only concerned with the updates of the `location` object in the Redux state
88
- // and completely ignores any updates to the URL in the web browser's address bar.
89
- //
90
- // So here, the "middleware" attempts to prevent or allow navigation that has already happened
91
- // in the web browser's address bar but hasn't yet happened in Redux state.
92
- // For example, it could be a user clicking a "Back"/"Forward" button in their web browser.
93
- // If such navigation should've been blocked, it will simply not update the `locaiton` object in Redux state,
94
- // and it will also "rewind" the change of the URL in the web browser's address bar so that it's consistent
95
- // with the `location` in Redux state.
96
- //
97
- case _ActionTypes.default.UPDATE:
98
- // If no navigation blockers to run, don't do anything.
99
- if ((0, _navigationBlockers.getNavigationBlockers)(session).length === 0) {
100
- return next(action);
101
- }
102
-
103
- // If it was the initial page load or a redirect,
104
- // it's not really a navigation that could be rolled back.
105
- if (payload.delta === 0) {
106
- return next(action);
107
- }
108
-
109
- // It's not really possible for a location to not have a `delta` property in a web browser session.
110
- // So this case is not something that's supposed to happen in real life.
111
- // Rather, it's a guard against an unsupported or incorrect session implementation or something like that.
112
- // If there's no `delta` property on the location, it means that the previous location can't be rewound to,
113
- // so it can't really "prevent" the navigation that has just happened.
114
- if (payload.delta === null) {
115
- return next(action);
116
- }
117
- result = (0, _navigationBlockers.runNavigationBlockers)((0, _navigationBlockers.getNavigationBlockers)(session), payload);
118
- if ((0, _isPromise.default)(result)) {
119
- const status = createNavigationBlockersEvaluationStatus();
120
-
121
- // While location blockers are running, rewind to the previous location.
122
- ignoreLocationSubscriptionEvents(() => {
123
- session.navigation.shift(-payload.delta);
124
- });
125
- result.then(promiseResult => {
126
- if (promiseResult) {
127
- // Navigation blocked.
128
- // Already rewound to a previous location.
129
- } else if (!status.cancelled) {
130
- // Navigation not blocked.
131
- // Rewind back to the new location.
132
- ignoreLocationSubscriptionEvents(() => {
133
- session.navigation.shift(payload.delta);
134
- });
135
- // Update the location.
136
- next(action);
137
- }
138
- });
139
- } else if (result) {
140
- // Prevent the navigation: rewind to the previous location.
141
- ignoreLocationSubscriptionEvents(() => {
142
- session.navigation.shift(-payload.delta);
143
- });
144
- } else {
145
- // Update the location.
146
- return next(action);
147
- }
148
- // eslint-disable-next-line consistent-return
149
- return;
150
-
151
- // Remove any navigation blockers on `DISPOSE` event.
152
- case _ActionTypes.default.DISPOSE:
153
- (0, _navigationBlockers.removeAllNavigationBlockers)(session);
154
- return next(action);
155
- default:
156
- return next(action);
157
- }
158
- };
159
- };
160
- }
161
- module.exports = exports.default;
@@ -1,38 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = createTransformLocationMiddleware;
5
- var _ActionTypes = _interopRequireDefault(require("../ActionTypes"));
6
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
- // Creates a "middleware" that transforms action payload (location).
8
- function createTransformLocationMiddleware({
9
- transformInputLocation,
10
- transformSubscriptionLocation
11
- }) {
12
- return function transformLocationMiddleware() {
13
- return next => action => {
14
- const {
15
- type,
16
- payload
17
- } = action;
18
- switch (type) {
19
- // Transforms `NAVIGATE` action payload (`location`).
20
- case _ActionTypes.default.NAVIGATE:
21
- return next({
22
- type,
23
- payload: transformInputLocation(payload)
24
- });
25
-
26
- // Transforms `UPDATE` action payload (input `location`).
27
- case _ActionTypes.default.UPDATE:
28
- return next({
29
- type,
30
- payload: transformSubscriptionLocation(payload)
31
- });
32
- default:
33
- return next(action);
34
- }
35
- };
36
- };
37
- }
38
- module.exports = exports.default;
@@ -1,10 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = onlyAllowedOnClientSide;
5
- function onlyAllowedOnClientSide() {
6
- if (typeof window === 'undefined') {
7
- throw new Error('This function can only be called on client side');
8
- }
9
- }
10
- module.exports = exports.default;