@merkur/plugin-router 0.27.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.
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2020 Miroslav Jancarik jancarikmiroslav@gmail.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ <center>
2
+ <h1 style="font-family: Helvetica, Arial, sans-serif; font-size:60px;">Merkur</h1>
3
+ </center>
4
+
5
+ [![Build Status](https://github.com/mjancarik/merkur/workflows/CI/badge.svg)](https://travis-ci.com/mjancarik/merkur)
6
+ [![NPM package version](https://img.shields.io/npm/v/@merkur/plugin-router/latest.svg)](https://www.npmjs.com/package/@merkur/core)
7
+ ![npm bundle size (scoped version)](https://img.shields.io/bundlephobia/minzip/@merkur/plugin-router/latest)
8
+ [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
9
+
10
+ # Merkur
11
+
12
+ The [Merkur](https://merkur.js.org/) is tiny extensible javascript library for front-end microservices. It allows by default server side rendering for loading performance boost. You can connect it with other frameworks or languages because merkur defines easy API. You can use one of four predefined template's library [React](https://reactjs.org/), [Preact](https://preactjs.com/), [hyperHTML](https://viperhtml.js.org/hyper.html) and [µhtml](https://github.com/WebReflection/uhtml#readme) but you can easily extend for others.
13
+
14
+ ## Getting started
15
+
16
+ ```bash
17
+ npx @merkur/create-widget <name>
18
+
19
+ cd name
20
+
21
+ npm run dev // Point your browser at http://localhost:4444/
22
+ ```
23
+ <p align="center">
24
+ <img alt="Merkur example, hello widget" src="https://raw.githubusercontent.com/mjancarik/merkur/master/images/hello-widget.png" />
25
+ </p>
26
+
27
+ You can see live [demo](https://merkur.js.org/demo).
28
+
29
+ ## API
30
+
31
+ Point your browser at `http://localhost:4444/widget`.
32
+
33
+ ```json
34
+ {
35
+ "name":"my-widget",
36
+ "version":"0.0.1",
37
+ "props":{},
38
+ "state":{"counter":0},
39
+ "assets":[
40
+ {
41
+ "name": "widget.js",
42
+ "type": "script",
43
+ "source": {
44
+ "es9": "http://localhost:4444/static/es9/widget.6961af42bfa3596bb147.js",
45
+ "es5": "http://localhost:4444/static/es5/widget.31c5090d8c961e43fade.js"
46
+ }
47
+ },
48
+ {
49
+ "name": "widget.css",
50
+ "type": "stylesheet",
51
+ "source": "http://localhost:4444/static/es9/widget.814e0cb568c7ddc0725d.css"
52
+ }
53
+ ],
54
+ "html":"\n <div class=\"merkur__page\">\n <div class=\"merkur__headline\">\n <div class=\"merkur__view\">\n \n <div class=\"merkur__icon\">\n <img src=\"http://localhost:4444/static/merkur-icon.png\" alt=\"Merkur\">\n </div>\n \n \n <h1>Welcome to <a href=\"https://github.com/mjancarik/merkur\">MERKUR</a>,<br> a javascript library for front-end microservices.</h1>\n \n \n <p>The widget's name is <strong>my-widget@0.0.1</strong>.</p>\n \n </div>\n </div>\n <div class=\"merkur__view\">\n \n <div>\n <h2>Counter widget:</h2>\n <p>Count: 0</p>\n <button onclick=\"return ((...rest) =&gt; {\n return originalFunction(widget, ...rest);\n }).call(this, event)\">\n increase counter\n </button>\n <button onclick=\"return ((...rest) =&gt; {\n return originalFunction(widget, ...rest);\n }).call(this, event)\">\n reset counter\n </button>\n </div>\n \n </div>\n </div>\n "
55
+ }
56
+ ```
package/jest.config.js ADDED
@@ -0,0 +1,5 @@
1
+ const defaultConfig = require('../../jest.config.js');
2
+
3
+ defaultConfig.testEnvironment = 'jsdom';
4
+
5
+ module.exports = { ...defaultConfig };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var RouterEvents = Object.freeze({
6
+ REDIRECT: '@merkur/plugin-router.redirect',
7
+ });
8
+
9
+ exports['default'] = RouterEvents;
@@ -0,0 +1 @@
1
+ "use strict";require("core-js/modules/es.object.define-property.js"),require("core-js/modules/es.object.freeze.js"),Object.defineProperty(exports,"__esModule",{value:!0});var e=Object.freeze({REDIRECT:"@merkur/plugin-router.redirect"});exports.default=e;
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', {
4
+ value: true
5
+ });
6
+ var RouterEvents = Object.freeze({
7
+ REDIRECT: '@merkur/plugin-router.redirect'
8
+ });
9
+ exports['default'] = RouterEvents;
@@ -0,0 +1,4 @@
1
+ var RouterEvents = Object.freeze({
2
+ REDIRECT: '@merkur/plugin-router.redirect'
3
+ });
4
+ export { RouterEvents as default };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var RouterEvents = Object.freeze({
6
+ REDIRECT: '@merkur/plugin-router.redirect',
7
+ });
8
+
9
+ exports['default'] = RouterEvents;
@@ -0,0 +1,5 @@
1
+ var RouterEvents = Object.freeze({
2
+ REDIRECT: '@merkur/plugin-router.redirect',
3
+ });
4
+
5
+ export { RouterEvents as default };
package/lib/index.cjs ADDED
@@ -0,0 +1,249 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var core = require('@merkur/core');
6
+ var UniversalRouter = require('universal-router');
7
+ var generateUrls = require('universal-router/generateUrls');
8
+
9
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
+
11
+ var UniversalRouter__default = /*#__PURE__*/_interopDefaultLegacy(UniversalRouter);
12
+ var generateUrls__default = /*#__PURE__*/_interopDefaultLegacy(generateUrls);
13
+
14
+ var RouterEvents = Object.freeze({
15
+ REDIRECT: '@merkur/plugin-router.redirect',
16
+ });
17
+
18
+ const DEV = 'development';
19
+ const ENV =
20
+ typeof process !== 'undefined' && process && process.env
21
+ ? process.env.NODE_ENV
22
+ : DEV;
23
+
24
+ function createRouter(widget, routes, options) {
25
+ widget.$dependencies.router = new UniversalRouter__default['default'](routes, options);
26
+ widget.$dependencies.link = generateUrls__default['default'](widget.$dependencies.router);
27
+ }
28
+
29
+ function routerPlugin() {
30
+ return {
31
+ async setup(widget) {
32
+ widget = {
33
+ ...routerAPI(),
34
+ ...widget,
35
+ };
36
+
37
+ widget.$in.router = {
38
+ route: null,
39
+ pathname: null,
40
+ isMounting: false,
41
+ isRouteActivated: false,
42
+ isBootstrapCalled: false,
43
+ };
44
+
45
+ core.bindWidgetToFunctions(widget, widget.router);
46
+
47
+ return widget;
48
+ },
49
+ async create(widget) {
50
+ if (ENV === DEV) {
51
+ if (!widget.$in.component) {
52
+ throw new Error(
53
+ 'You must install missing plugin: npm i @merkur/plugin-component'
54
+ );
55
+ }
56
+
57
+ if (!widget.$in.eventEmitter) {
58
+ throw new Error(
59
+ 'You must install missing plugin: npm i @merkur/plugin-event-emitter'
60
+ );
61
+ }
62
+ }
63
+
64
+ widget.$in.component.lifeCycle = core.setDefaultValueForUndefined(
65
+ widget.$in.component.lifeCycle,
66
+ ['load'],
67
+ () => {}
68
+ );
69
+ core.hookMethod(widget, '$in.component.lifeCycle.load', loadHook);
70
+ core.hookMethod(widget, 'bootstrap', bootstrapHook);
71
+ core.hookMethod(widget, 'mount', mountHook);
72
+ core.hookMethod(widget, 'unmount', unmountHook);
73
+ core.hookMethod(widget, 'update', updateHook);
74
+
75
+ return widget;
76
+ },
77
+ };
78
+ }
79
+
80
+ function routerAPI() {
81
+ return {
82
+ router: {
83
+ redirect(widget, url, data = {}) {
84
+ widget.emit(RouterEvents.REDIRECT, { url, ...data });
85
+ },
86
+ link(widget, routeName, data = {}) {
87
+ return widget.$dependencies.link(routeName, data);
88
+ },
89
+ getCurrentRoute(widget) {
90
+ return widget.$in.router.route;
91
+ },
92
+ },
93
+ };
94
+ }
95
+
96
+ async function bootstrapHook(widget, originalBootstrap, ...rest) {
97
+ if (widget.$in.router.isBootstrapCalled) {
98
+ return;
99
+ }
100
+
101
+ widget.$in.router.isBootstrapCalled = true;
102
+
103
+ return originalBootstrap(...rest);
104
+ }
105
+
106
+ // hook Component
107
+ async function loadHook(widget, originalLoad, ...rest) {
108
+ const plugin = widget.$in.router;
109
+
110
+ if (!plugin.isMounting && widget.props.pathname !== plugin.pathname) {
111
+ await tearDownRouterCycle(widget, ...rest);
112
+
113
+ await setupRouterCycle(widget, ...rest);
114
+ }
115
+
116
+ if (!core.isFunction(plugin.route.load)) {
117
+ throw new Error('The load method is mandatory.');
118
+ }
119
+
120
+ const globalStatePromise = core.isFunction(originalLoad)
121
+ ? originalLoad(widget, ...rest)
122
+ : Promise.resolve({});
123
+ const routeStatePromise = plugin.route.load(widget, {
124
+ route: plugin.route,
125
+ args: rest,
126
+ globalState: globalStatePromise,
127
+ });
128
+
129
+ const [globalState, routeState] = await Promise.all([
130
+ globalStatePromise,
131
+ routeStatePromise,
132
+ ]);
133
+
134
+ return { ...globalState, ...routeState };
135
+ }
136
+
137
+ // hook Component
138
+ async function mountHook(widget, originalMount, ...rest) {
139
+ await widget.bootstrap(...rest);
140
+
141
+ const plugin = widget.$in.router;
142
+ if (!plugin.route) {
143
+ await resolveRoute(widget);
144
+ plugin.isMounting = true;
145
+ }
146
+
147
+ const result = await originalMount(...rest);
148
+
149
+ if (plugin.isMounting && core.isFunction(plugin.route.init)) {
150
+ await plugin.route.init(widget, { route: plugin.route, args: rest });
151
+ }
152
+
153
+ if (
154
+ core.isFunction(plugin.route.activate) &&
155
+ isClient() &&
156
+ !plugin.isRouteActivated
157
+ ) {
158
+ plugin.isRouteActivated = true;
159
+ plugin.route.activate(widget, { route: plugin.route, args: rest });
160
+ }
161
+
162
+ plugin.isMounting = false;
163
+
164
+ return result;
165
+ }
166
+
167
+ // hook Component
168
+ async function updateHook(widget, originalUpdate, ...rest) {
169
+ const result = await originalUpdate(...rest);
170
+
171
+ const plugin = widget.$in.router;
172
+
173
+ if (
174
+ core.isFunction(plugin.route.activate) &&
175
+ isClient() &&
176
+ !plugin.isRouteActivated
177
+ ) {
178
+ plugin.isRouteActivated = true;
179
+ plugin.route.activate(widget, { route: plugin.route, args: rest });
180
+ }
181
+
182
+ return result;
183
+ }
184
+
185
+ // hook Component
186
+ async function unmountHook(widget, originalUnmount, ...rest) {
187
+ const result = await originalUnmount(...rest);
188
+
189
+ await tearDownRouterCycle(widget, ...rest);
190
+
191
+ return result;
192
+ }
193
+
194
+ async function resolveRoute(widget) {
195
+ if (ENV === DEV) {
196
+ if (!widget.props.pathname) {
197
+ throw new Error('The props pathname is not defined.');
198
+ }
199
+
200
+ if (!widget.$dependencies.router) {
201
+ throw new Error(
202
+ 'You must add calling of createRouter(widget, routes, options) to widget.setup method.'
203
+ );
204
+ }
205
+ }
206
+
207
+ const route = await widget.$dependencies.router.resolve({
208
+ pathname: widget.props.pathname,
209
+ widget,
210
+ });
211
+
212
+ widget.$in.router.route = route;
213
+ widget.$in.router.pathname = widget.props.pathname;
214
+
215
+ return route;
216
+ }
217
+
218
+ async function setupRouterCycle(widget, ...rest) {
219
+ const route = await resolveRoute(widget);
220
+
221
+ if (core.isFunction(route.init)) {
222
+ await route.init(widget, { route, args: rest });
223
+ }
224
+ }
225
+
226
+ async function tearDownRouterCycle(widget, ...rest) {
227
+ const plugin = widget.$in.router;
228
+
229
+ const { route, isRouteActivated } = plugin;
230
+
231
+ if (route) {
232
+ if (core.isFunction(route.deactivate) && isRouteActivated === true) {
233
+ await route.deactivate(widget, { route, args: rest });
234
+ }
235
+
236
+ if (core.isFunction(route.destroy)) {
237
+ await route.destroy(widget, { route, args: rest });
238
+ }
239
+ }
240
+
241
+ plugin.isRouteActivated = false;
242
+ }
243
+
244
+ function isClient() {
245
+ return typeof window !== 'undefined';
246
+ }
247
+
248
+ exports.createRouter = createRouter;
249
+ exports.routerPlugin = routerPlugin;
@@ -0,0 +1 @@
1
+ "use strict";function e(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,r){var t=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null==t)return;var n,o,u=[],i=!0,a=!1;try{for(t=t.call(e);!(i=(n=t.next()).done)&&(u.push(n.value),!r||u.length!==r);i=!0);}catch(e){a=!0,o=e}finally{try{i||null==t.return||t.return()}finally{if(a)throw o}}return u}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function r(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=new Array(r);t<r;t++)n[t]=e[t];return n}function t(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function n(e){for(var r=1;r<arguments.length;r++){var n=null!=arguments[r]?arguments[r]:{};r%2?t(Object(n),!0).forEach((function(r){o(e,r,n[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):t(Object(n)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(n,r))}))}return e}function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function u(e,r,t,n,o,u,i){try{var a=e[u](i),s=a.value}catch(e){return void t(e)}a.done?r(s):Promise.resolve(s).then(n,o)}function i(e){return function(){var r=this,t=arguments;return new Promise((function(n,o){var i=e.apply(r,t);function a(e){u(i,n,o,a,s,"next",e)}function s(e){u(i,n,o,a,s,"throw",e)}a(void 0)}))}}function a(e){return a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a(e)}require("regenerator-runtime/runtime.js"),require("core-js/modules/es.object.define-property.js"),require("core-js/modules/es.object.freeze.js"),require("core-js/modules/es.string.link.js"),require("core-js/modules/es.array.concat.js"),require("core-js/modules/es.object.to-string.js"),require("core-js/modules/es.promise.js"),require("core-js/modules/es.array.iterator.js"),require("core-js/modules/es.string.iterator.js"),require("core-js/modules/web.dom-collections.iterator.js"),require("core-js/modules/es.symbol.js"),require("core-js/modules/es.symbol.description.js"),require("core-js/modules/es.symbol.iterator.js"),require("core-js/modules/es.object.keys.js"),require("core-js/modules/es.array.filter.js"),require("core-js/modules/es.object.get-own-property-descriptor.js"),require("core-js/modules/es.array.for-each.js"),require("core-js/modules/web.dom-collections.for-each.js"),require("core-js/modules/es.object.get-own-property-descriptors.js"),require("core-js/modules/es.object.define-properties.js"),require("core-js/modules/es.array.is-array.js"),require("core-js/modules/es.array.slice.js"),require("core-js/modules/es.function.name.js"),require("core-js/modules/es.array.from.js"),Object.defineProperty(exports,"__esModule",{value:!0});var s=require("@merkur/core"),c=require("universal-router"),p=require("universal-router/generateUrls");function l(e){return e&&"object"===a(e)&&"default"in e?e:{default:e}}var f=l(c),d=l(p),m=Object.freeze({REDIRECT:"@merkur/plugin-router.redirect"}),y="development",h="undefined"!=typeof process&&process&&process.env?process.env.NODE_ENV:y;function b(e,r){return g.apply(this,arguments)}function g(){return g=i(regeneratorRuntime.mark((function e(r,t){var n,o,u,i=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!r.$in.router.isBootstrapCalled){e.next=2;break}return e.abrupt("return");case 2:for(r.$in.router.isBootstrapCalled=!0,n=i.length,o=new Array(n>2?n-2:0),u=2;u<n;u++)o[u-2]=i[u];return e.abrupt("return",t.apply(void 0,o));case 5:case"end":return e.stop()}}),e)}))),g.apply(this,arguments)}function v(e,r){return j.apply(this,arguments)}function j(){return j=i(regeneratorRuntime.mark((function r(t,o){var u,i,a,c,p,l,f,d,m,y,h=arguments;return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:for(u=t.$in.router,i=h.length,a=new Array(i>2?i-2:0),c=2;c<i;c++)a[c-2]=h[c];if(u.isMounting||t.props.pathname===u.pathname){r.next=7;break}return r.next=5,S.apply(void 0,[t].concat(a));case 5:return r.next=7,E.apply(void 0,[t].concat(a));case 7:if(s.isFunction(u.route.load)){r.next=9;break}throw new Error("The load method is mandatory.");case 9:return p=s.isFunction(o)?o.apply(void 0,[t].concat(a)):Promise.resolve({}),l=u.route.load(t,{route:u.route,args:a,globalState:p}),r.next=13,Promise.all([p,l]);case 13:return f=r.sent,d=e(f,2),m=d[0],y=d[1],r.abrupt("return",n(n({},m),y));case 18:case"end":return r.stop()}}),r)}))),j.apply(this,arguments)}function w(e,r){return x.apply(this,arguments)}function x(){return x=i(regeneratorRuntime.mark((function e(r,t){var n,o,u,i,a,c=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:for(n=c.length,o=new Array(n>2?n-2:0),u=2;u<n;u++)o[u-2]=c[u];return e.next=3,r.bootstrap.apply(r,o);case 3:if((i=r.$in.router).route){e.next=8;break}return e.next=7,$(r);case 7:i.isMounting=!0;case 8:return e.next=10,t.apply(void 0,o);case 10:if(a=e.sent,!i.isMounting||!s.isFunction(i.route.init)){e.next=14;break}return e.next=14,i.route.init(r,{route:i.route,args:o});case 14:return s.isFunction(i.route.activate)&&C()&&!i.isRouteActivated&&(i.isRouteActivated=!0,i.route.activate(r,{route:i.route,args:o})),i.isMounting=!1,e.abrupt("return",a);case 17:case"end":return e.stop()}}),e)}))),x.apply(this,arguments)}function k(e,r){return R.apply(this,arguments)}function R(){return R=i(regeneratorRuntime.mark((function e(r,t){var n,o,u,i,a,c=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:for(n=c.length,o=new Array(n>2?n-2:0),u=2;u<n;u++)o[u-2]=c[u];return e.next=3,t.apply(void 0,o);case 3:return i=e.sent,a=r.$in.router,s.isFunction(a.route.activate)&&C()&&!a.isRouteActivated&&(a.isRouteActivated=!0,a.route.activate(r,{route:a.route,args:o})),e.abrupt("return",i);case 7:case"end":return e.stop()}}),e)}))),R.apply(this,arguments)}function q(e,r){return O.apply(this,arguments)}function O(){return O=i(regeneratorRuntime.mark((function e(r,t){var n,o,u,i,a=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:for(n=a.length,o=new Array(n>2?n-2:0),u=2;u<n;u++)o[u-2]=a[u];return e.next=3,t.apply(void 0,o);case 3:return i=e.sent,e.next=6,S.apply(void 0,[r].concat(o));case 6:return e.abrupt("return",i);case 7:case"end":return e.stop()}}),e)}))),O.apply(this,arguments)}function $(e){return A.apply(this,arguments)}function A(){return(A=i(regeneratorRuntime.mark((function e(r){var t;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(h!==y){e.next=5;break}if(r.props.pathname){e.next=3;break}throw new Error("The props pathname is not defined.");case 3:if(r.$dependencies.router){e.next=5;break}throw new Error("You must add calling of createRouter(widget, routes, options) to widget.setup method.");case 5:return e.next=7,r.$dependencies.router.resolve({pathname:r.props.pathname,widget:r});case 7:return t=e.sent,r.$in.router.route=t,r.$in.router.pathname=r.props.pathname,e.abrupt("return",t);case 11:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function E(e){return P.apply(this,arguments)}function P(){return P=i(regeneratorRuntime.mark((function e(r){var t,n,o,u,i=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,$(r);case 2:if(t=e.sent,!s.isFunction(t.init)){e.next=7;break}for(n=i.length,o=new Array(n>1?n-1:0),u=1;u<n;u++)o[u-1]=i[u];return e.next=7,t.init(r,{route:t,args:o});case 7:case"end":return e.stop()}}),e)}))),P.apply(this,arguments)}function S(e){return M.apply(this,arguments)}function M(){return M=i(regeneratorRuntime.mark((function e(r){var t,n,o,u,i,a,c=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(t=r.$in.router,n=t.route,o=t.isRouteActivated,!n){e.next=10;break}for(u=c.length,i=new Array(u>1?u-1:0),a=1;a<u;a++)i[a-1]=c[a];if(!s.isFunction(n.deactivate)||!0!==o){e.next=7;break}return e.next=7,n.deactivate(r,{route:n,args:i});case 7:if(!s.isFunction(n.destroy)){e.next=10;break}return e.next=10,n.destroy(r,{route:n,args:i});case 10:t.isRouteActivated=!1;case 11:case"end":return e.stop()}}),e)}))),M.apply(this,arguments)}function C(){return"undefined"!=typeof window}exports.createRouter=function(e,r,t){e.$dependencies.router=new f.default(r,t),e.$dependencies.link=d.default(e.$dependencies.router)},exports.routerPlugin=function(){return{setup:function(e){return i(regeneratorRuntime.mark((function r(){return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:return e=n(n({},{router:{redirect:function(e,r){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};e.emit(m.REDIRECT,n({url:r},t))},link:function(e,r){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return e.$dependencies.link(r,t)},getCurrentRoute:function(e){return e.$in.router.route}}}),e),e.$in.router={route:null,pathname:null,isMounting:!1,isRouteActivated:!1,isBootstrapCalled:!1},s.bindWidgetToFunctions(e,e.router),r.abrupt("return",e);case 4:case"end":return r.stop()}}),r)})))()},create:function(e){return i(regeneratorRuntime.mark((function r(){return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:if(h!==y){r.next=5;break}if(e.$in.component){r.next=3;break}throw new Error("You must install missing plugin: npm i @merkur/plugin-component");case 3:if(e.$in.eventEmitter){r.next=5;break}throw new Error("You must install missing plugin: npm i @merkur/plugin-event-emitter");case 5:return e.$in.component.lifeCycle=s.setDefaultValueForUndefined(e.$in.component.lifeCycle,["load"],(function(){})),s.hookMethod(e,"$in.component.lifeCycle.load",v),s.hookMethod(e,"bootstrap",b),s.hookMethod(e,"mount",w),s.hookMethod(e,"unmount",q),s.hookMethod(e,"update",k),r.abrupt("return",e);case 12:case"end":return r.stop()}}),r)})))()}}};
@@ -0,0 +1,246 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', {
4
+ value: true
5
+ });
6
+
7
+ var core = require('@merkur/core');
8
+
9
+ var UniversalRouter = require('universal-router');
10
+
11
+ var generateUrls = require('universal-router/generateUrls');
12
+
13
+ function _interopDefaultLegacy(e) {
14
+ return e && typeof e === 'object' && 'default' in e ? e : {
15
+ 'default': e
16
+ };
17
+ }
18
+
19
+ var UniversalRouter__default = /*#__PURE__*/_interopDefaultLegacy(UniversalRouter);
20
+
21
+ var generateUrls__default = /*#__PURE__*/_interopDefaultLegacy(generateUrls);
22
+
23
+ var RouterEvents = Object.freeze({
24
+ REDIRECT: '@merkur/plugin-router.redirect'
25
+ });
26
+ const DEV = 'development';
27
+ const ENV = typeof process !== 'undefined' && process && process.env ? process.env.NODE_ENV : DEV;
28
+
29
+ function createRouter(widget, routes, options) {
30
+ widget.$dependencies.router = new UniversalRouter__default['default'](routes, options);
31
+ widget.$dependencies.link = generateUrls__default['default'](widget.$dependencies.router);
32
+ }
33
+
34
+ function routerPlugin() {
35
+ return {
36
+ async setup(widget) {
37
+ widget = { ...routerAPI(),
38
+ ...widget
39
+ };
40
+ widget.$in.router = {
41
+ route: null,
42
+ pathname: null,
43
+ isMounting: false,
44
+ isRouteActivated: false,
45
+ isBootstrapCalled: false
46
+ };
47
+ core.bindWidgetToFunctions(widget, widget.router);
48
+ return widget;
49
+ },
50
+
51
+ async create(widget) {
52
+ if (ENV === DEV) {
53
+ if (!widget.$in.component) {
54
+ throw new Error('You must install missing plugin: npm i @merkur/plugin-component');
55
+ }
56
+
57
+ if (!widget.$in.eventEmitter) {
58
+ throw new Error('You must install missing plugin: npm i @merkur/plugin-event-emitter');
59
+ }
60
+ }
61
+
62
+ widget.$in.component.lifeCycle = core.setDefaultValueForUndefined(widget.$in.component.lifeCycle, ['load'], () => {});
63
+ core.hookMethod(widget, '$in.component.lifeCycle.load', loadHook);
64
+ core.hookMethod(widget, 'bootstrap', bootstrapHook);
65
+ core.hookMethod(widget, 'mount', mountHook);
66
+ core.hookMethod(widget, 'unmount', unmountHook);
67
+ core.hookMethod(widget, 'update', updateHook);
68
+ return widget;
69
+ }
70
+
71
+ };
72
+ }
73
+
74
+ function routerAPI() {
75
+ return {
76
+ router: {
77
+ redirect(widget, url, data = {}) {
78
+ widget.emit(RouterEvents.REDIRECT, {
79
+ url,
80
+ ...data
81
+ });
82
+ },
83
+
84
+ link(widget, routeName, data = {}) {
85
+ return widget.$dependencies.link(routeName, data);
86
+ },
87
+
88
+ getCurrentRoute(widget) {
89
+ return widget.$in.router.route;
90
+ }
91
+
92
+ }
93
+ };
94
+ }
95
+
96
+ async function bootstrapHook(widget, originalBootstrap, ...rest) {
97
+ if (widget.$in.router.isBootstrapCalled) {
98
+ return;
99
+ }
100
+
101
+ widget.$in.router.isBootstrapCalled = true;
102
+ return originalBootstrap(...rest);
103
+ } // hook Component
104
+
105
+
106
+ async function loadHook(widget, originalLoad, ...rest) {
107
+ const plugin = widget.$in.router;
108
+
109
+ if (!plugin.isMounting && widget.props.pathname !== plugin.pathname) {
110
+ await tearDownRouterCycle(widget, ...rest);
111
+ await setupRouterCycle(widget, ...rest);
112
+ }
113
+
114
+ if (!core.isFunction(plugin.route.load)) {
115
+ throw new Error('The load method is mandatory.');
116
+ }
117
+
118
+ const globalStatePromise = core.isFunction(originalLoad) ? originalLoad(widget, ...rest) : Promise.resolve({});
119
+ const routeStatePromise = plugin.route.load(widget, {
120
+ route: plugin.route,
121
+ args: rest,
122
+ globalState: globalStatePromise
123
+ });
124
+ const [globalState, routeState] = await Promise.all([globalStatePromise, routeStatePromise]);
125
+ return { ...globalState,
126
+ ...routeState
127
+ };
128
+ } // hook Component
129
+
130
+
131
+ async function mountHook(widget, originalMount, ...rest) {
132
+ await widget.bootstrap(...rest);
133
+ const plugin = widget.$in.router;
134
+
135
+ if (!plugin.route) {
136
+ await resolveRoute(widget);
137
+ plugin.isMounting = true;
138
+ }
139
+
140
+ const result = await originalMount(...rest);
141
+
142
+ if (plugin.isMounting && core.isFunction(plugin.route.init)) {
143
+ await plugin.route.init(widget, {
144
+ route: plugin.route,
145
+ args: rest
146
+ });
147
+ }
148
+
149
+ if (core.isFunction(plugin.route.activate) && isClient() && !plugin.isRouteActivated) {
150
+ plugin.isRouteActivated = true;
151
+ plugin.route.activate(widget, {
152
+ route: plugin.route,
153
+ args: rest
154
+ });
155
+ }
156
+
157
+ plugin.isMounting = false;
158
+ return result;
159
+ } // hook Component
160
+
161
+
162
+ async function updateHook(widget, originalUpdate, ...rest) {
163
+ const result = await originalUpdate(...rest);
164
+ const plugin = widget.$in.router;
165
+
166
+ if (core.isFunction(plugin.route.activate) && isClient() && !plugin.isRouteActivated) {
167
+ plugin.isRouteActivated = true;
168
+ plugin.route.activate(widget, {
169
+ route: plugin.route,
170
+ args: rest
171
+ });
172
+ }
173
+
174
+ return result;
175
+ } // hook Component
176
+
177
+
178
+ async function unmountHook(widget, originalUnmount, ...rest) {
179
+ const result = await originalUnmount(...rest);
180
+ await tearDownRouterCycle(widget, ...rest);
181
+ return result;
182
+ }
183
+
184
+ async function resolveRoute(widget) {
185
+ if (ENV === DEV) {
186
+ if (!widget.props.pathname) {
187
+ throw new Error('The props pathname is not defined.');
188
+ }
189
+
190
+ if (!widget.$dependencies.router) {
191
+ throw new Error('You must add calling of createRouter(widget, routes, options) to widget.setup method.');
192
+ }
193
+ }
194
+
195
+ const route = await widget.$dependencies.router.resolve({
196
+ pathname: widget.props.pathname,
197
+ widget
198
+ });
199
+ widget.$in.router.route = route;
200
+ widget.$in.router.pathname = widget.props.pathname;
201
+ return route;
202
+ }
203
+
204
+ async function setupRouterCycle(widget, ...rest) {
205
+ const route = await resolveRoute(widget);
206
+
207
+ if (core.isFunction(route.init)) {
208
+ await route.init(widget, {
209
+ route,
210
+ args: rest
211
+ });
212
+ }
213
+ }
214
+
215
+ async function tearDownRouterCycle(widget, ...rest) {
216
+ const plugin = widget.$in.router;
217
+ const {
218
+ route,
219
+ isRouteActivated
220
+ } = plugin;
221
+
222
+ if (route) {
223
+ if (core.isFunction(route.deactivate) && isRouteActivated === true) {
224
+ await route.deactivate(widget, {
225
+ route,
226
+ args: rest
227
+ });
228
+ }
229
+
230
+ if (core.isFunction(route.destroy)) {
231
+ await route.destroy(widget, {
232
+ route,
233
+ args: rest
234
+ });
235
+ }
236
+ }
237
+
238
+ plugin.isRouteActivated = false;
239
+ }
240
+
241
+ function isClient() {
242
+ return typeof window !== 'undefined';
243
+ }
244
+
245
+ exports.createRouter = createRouter;
246
+ exports.routerPlugin = routerPlugin;