@module-federation/nextjs-mf 5.2.2 → 5.3.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 (38) hide show
  1. package/lib/NextFederationPlugin2.js +0 -0
  2. package/lib/_virtual/UrlNode.js +8 -0
  3. package/lib/_virtual/_commonjsHelpers.js +26 -0
  4. package/lib/_virtual/_tslib.js +101 -0
  5. package/lib/_virtual/helpers.js +7 -0
  6. package/lib/_virtual/nextPageMapLoader.js +7 -0
  7. package/lib/client/CombinedPages.d.ts +28 -0
  8. package/lib/client/CombinedPages.d.ts.map +1 -0
  9. package/lib/client/CombinedPages.js +60 -0
  10. package/lib/client/MFClient.d.ts +70 -0
  11. package/lib/client/MFClient.d.ts.map +1 -0
  12. package/lib/client/MFClient.js +197 -0
  13. package/lib/client/RemoteContainer.d.ts +58 -0
  14. package/lib/client/RemoteContainer.d.ts.map +1 -0
  15. package/lib/client/RemoteContainer.js +161 -0
  16. package/lib/client/RemotePages.d.ts +48 -0
  17. package/lib/client/RemotePages.d.ts.map +1 -0
  18. package/lib/client/RemotePages.js +168 -0
  19. package/lib/client/UrlNode.d.ts +18 -0
  20. package/lib/client/UrlNode.d.ts.map +1 -0
  21. package/lib/client/UrlNode.js +162 -0
  22. package/lib/client/helpers.d.ts +17 -0
  23. package/lib/client/helpers.d.ts.map +1 -0
  24. package/lib/client/helpers.js +108 -0
  25. package/lib/client/useMFClient.d.ts +25 -0
  26. package/lib/client/useMFClient.d.ts.map +1 -0
  27. package/lib/client/useMFClient.js +79 -0
  28. package/lib/client/useMFRemote.d.ts +17 -0
  29. package/lib/client/useMFRemote.d.ts.map +1 -0
  30. package/lib/client/useMFRemote.js +72 -0
  31. package/lib/loaders/UrlNode.js +215 -0
  32. package/lib/loaders/helpers.js +10 -3
  33. package/lib/loaders/nextPageMapLoader.js +81 -17
  34. package/lib/loaders/patchNextClientPageLoader.js +53 -0
  35. package/lib/plugins/DevHmrFixInvalidPongPlugin.js +65 -0
  36. package/lib/utils.js +7 -3
  37. package/package.json +21 -4
  38. package/tsconfig.json +33 -0
@@ -0,0 +1,108 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _tslib = require('../_virtual/_tslib.js');
6
+ var UrlNode = require('./UrlNode.js');
7
+
8
+ var TEST_DYNAMIC_ROUTE = /\/\[[^/]+?\](?=\/|$)/;
9
+ function isDynamicRoute(route) {
10
+ return TEST_DYNAMIC_ROUTE.test(route);
11
+ }
12
+ /**
13
+ * Parses a given parameter from a route to a data structure that can be used
14
+ * to generate the parametrized route. Examples:
15
+ * - `[...slug]` -> `{ name: 'slug', repeat: true, optional: true }`
16
+ * - `[foo]` -> `{ name: 'foo', repeat: false, optional: true }`
17
+ * - `bar` -> `{ name: 'bar', repeat: false, optional: false }`
18
+ */
19
+ function parseParameter(param) {
20
+ var optional = param.startsWith('[') && param.endsWith(']');
21
+ if (optional) {
22
+ param = param.slice(1, -1);
23
+ }
24
+ var repeat = param.startsWith('...');
25
+ if (repeat) {
26
+ param = param.slice(3);
27
+ }
28
+ return { key: param, repeat: repeat, optional: optional };
29
+ }
30
+ function getParametrizedRoute(route) {
31
+ // const segments = removeTrailingSlash(route).slice(1).split('/')
32
+ var segments = route.slice(1).split('/');
33
+ var groups = {};
34
+ var groupIndex = 1;
35
+ return {
36
+ parameterizedRoute: segments
37
+ .map(function (segment) {
38
+ if (segment.startsWith('[') && segment.endsWith(']')) {
39
+ var _a = parseParameter(segment.slice(1, -1)), key = _a.key, optional = _a.optional, repeat = _a.repeat;
40
+ groups[key] = { pos: groupIndex++, repeat: repeat, optional: optional };
41
+ return repeat ? (optional ? '(?:/(.+?))?' : '/(.+?)') : '/([^/]+?)';
42
+ }
43
+ else {
44
+ return "/".concat(escapeStringRegexp(segment));
45
+ }
46
+ })
47
+ .join(''),
48
+ groups: groups,
49
+ };
50
+ }
51
+ function getRouteRegex(normalizedRoute) {
52
+ var _a = getParametrizedRoute(normalizedRoute), parameterizedRoute = _a.parameterizedRoute, groups = _a.groups;
53
+ return {
54
+ re: new RegExp("^".concat(parameterizedRoute, "(?:/)?$")),
55
+ groups: groups,
56
+ };
57
+ }
58
+ var reHasRegExp = /[|\\{}()[\]^$+*?.-]/;
59
+ var reReplaceRegExp = /[|\\{}()[\]^$+*?.-]/g;
60
+ function escapeStringRegexp(str) {
61
+ // see also: https://github.com/lodash/lodash/blob/2da024c3b4f9947a48517639de7560457cd4ec6c/escapeRegExp.js#L23
62
+ if (reHasRegExp.test(str)) {
63
+ return str.replace(reReplaceRegExp, '\\$&');
64
+ }
65
+ return str;
66
+ }
67
+ /**
68
+ * Convert browser pathname to NextJs route.
69
+ * This method is required for proper work of Dynamic routes in NextJS.
70
+ */
71
+ function pathnameToRoute(cleanPathname, routes) {
72
+ var e_1, _a;
73
+ if (routes.includes(cleanPathname)) {
74
+ return cleanPathname;
75
+ }
76
+ try {
77
+ for (var routes_1 = _tslib.__values(routes), routes_1_1 = routes_1.next(); !routes_1_1.done; routes_1_1 = routes_1.next()) {
78
+ var route = routes_1_1.value;
79
+ if (isDynamicRoute(route) && getRouteRegex(route).re.test(cleanPathname)) {
80
+ return route;
81
+ }
82
+ }
83
+ }
84
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
85
+ finally {
86
+ try {
87
+ if (routes_1_1 && !routes_1_1.done && (_a = routes_1.return)) _a.call(routes_1);
88
+ }
89
+ finally { if (e_1) throw e_1.error; }
90
+ }
91
+ return undefined;
92
+ }
93
+ /**
94
+ * Sort provided pages in correct nextjs order.
95
+ * This sorting is required if you are using dynamic routes in your apps.
96
+ * If order is incorrect then Nextjs may use dynamicRoute instead of exact page.
97
+ */
98
+ function sortNextPages(pages) {
99
+ var root = new UrlNode.UrlNode();
100
+ pages.forEach(function (pageRoute) { return root.insert(pageRoute); });
101
+ // Smoosh will then sort those sublevels up to the point where you get the correct route definition priority
102
+ return root.smoosh();
103
+ }
104
+
105
+ exports.getRouteRegex = getRouteRegex;
106
+ exports.isDynamicRoute = isDynamicRoute;
107
+ exports.pathnameToRoute = pathnameToRoute;
108
+ exports.sortNextPages = sortNextPages;
@@ -0,0 +1,25 @@
1
+ import type { MFClient } from './MFClient';
2
+ import type { RemoteContainer } from './RemoteContainer';
3
+ export declare type MFClientHookOptions = {
4
+ /**
5
+ * This callback will be called when user switches to federated page
6
+ * - as a first arg you will receive RemoteContainer
7
+ * If user return back to the host application page
8
+ * - then the first argument became `undefined`
9
+ *
10
+ * This callback is called only if changed remote from which served current visible page
11
+ * and does not called on internal nextjs route changes.
12
+ *
13
+ * This callback helps in very convenient way in _app.tsx (or any other React component)
14
+ * load additional data from RemoteContainer and pass it to your application. Eg.:
15
+ * - application menu
16
+ * - apollo configs
17
+ * - translation strings
18
+ */
19
+ onChangeRemote?: (remote: RemoteContainer | undefined, MFClient: MFClient) => void;
20
+ };
21
+ /**
22
+ * React hook which provides convenient way for working with ModuleFederation runtime changes in runtime;
23
+ */
24
+ export declare function useMFClient(opts: MFClientHookOptions): MFClient;
25
+ //# sourceMappingURL=useMFClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMFClient.d.ts","sourceRoot":"","sources":["../../src/client/useMFClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD,oBAAY,mBAAmB,GAAG;IAChC;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,EAAE,CACf,MAAM,EAAE,eAAe,GAAG,SAAS,EACnC,QAAQ,EAAE,QAAQ,KACf,IAAI,CAAC;CACX,CAAC;AAQF;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,mBAAmB,GAAG,QAAQ,CAgD/D"}
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var React = require('react');
6
+ var singletonRouter = require('next/dist/client/router');
7
+
8
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n["default"] = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
29
+ var singletonRouter__default = /*#__PURE__*/_interopDefaultLegacy(singletonRouter);
30
+
31
+ var isBrowser = typeof window !== 'undefined';
32
+ /**
33
+ * React hook which provides convenient way for working with ModuleFederation runtime changes in runtime;
34
+ */
35
+ function useMFClient(opts) {
36
+ var MFClient = isBrowser
37
+ ? window.mf_client
38
+ : /* TODO: inject here SSR version of MFClient if it will be needed in future */ {};
39
+ var innerState = React__namespace.useRef({
40
+ remote: undefined,
41
+ });
42
+ React__namespace.useEffect(function () {
43
+ // Step 1: Define handlers and helpers
44
+ var processRemoteChange = function (remote) {
45
+ if (innerState.current.remote !== remote) {
46
+ innerState.current.remote = remote;
47
+ if (opts === null || opts === void 0 ? void 0 : opts.onChangeRemote) {
48
+ opts.onChangeRemote(remote, MFClient);
49
+ }
50
+ }
51
+ };
52
+ var handleRouterChange = function (pathname) {
53
+ if (MFClient.isFederatedPathname(pathname)) {
54
+ var remote = MFClient.remotePages.routeToRemote(pathname);
55
+ processRemoteChange(remote);
56
+ }
57
+ else {
58
+ processRemoteChange(undefined);
59
+ }
60
+ };
61
+ // Step 2: run bootstrap logic
62
+ var initialRemote = MFClient.isFederatedPathname(window.location.pathname)
63
+ ? MFClient.remotePages.routeToRemote(window.location.pathname)
64
+ : undefined;
65
+ if (initialRemote) {
66
+ // important for first load to fire `onChangeRemote` with different remote
67
+ // because in innerState by default we assume that used local application
68
+ processRemoteChange(initialRemote);
69
+ }
70
+ // Step 3: Subscribe on events
71
+ singletonRouter__default["default"].events.on('routeChangeStart', handleRouterChange);
72
+ return function () {
73
+ singletonRouter__default["default"].events.off('routeChangeStart', handleRouterChange);
74
+ };
75
+ }, []);
76
+ return MFClient;
77
+ }
78
+
79
+ exports.useMFClient = useMFClient;
@@ -0,0 +1,17 @@
1
+ import { RemoteContainer } from './RemoteContainer';
2
+ declare type UseMFRemoteResult = {
3
+ /** is container loaded or not */
4
+ loaded: boolean;
5
+ /** remote is Lazy, so it will be loaded if getModule(), getContainer() were called */
6
+ remote: RemoteContainer;
7
+ /** Present if error occurs during remote container loading */
8
+ error: Error | undefined;
9
+ };
10
+ /**
11
+ * React hook which provides an access to RemoteContainer in Module Federation
12
+ *
13
+ * @param global - can be a global variable name OR connection string "global@url"
14
+ */
15
+ export declare function useMFRemote(global: string): UseMFRemoteResult;
16
+ export {};
17
+ //# sourceMappingURL=useMFRemote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMFRemote.d.ts","sourceRoot":"","sources":["../../src/client/useMFRemote.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,aAAK,iBAAiB,GAAG;IACvB,iCAAiC;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,sFAAsF;IACtF,MAAM,EAAE,eAAe,CAAC;IACxB,8DAA8D;IAC9D,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;CAC1B,CAAC;AAIF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAwC7D"}
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _tslib = require('../_virtual/_tslib.js');
6
+ var React = require('react');
7
+ var RemoteContainer = require('./RemoteContainer.js');
8
+
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n["default"] = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
28
+
29
+ var isBrowser = typeof window !== 'undefined';
30
+ /**
31
+ * React hook which provides an access to RemoteContainer in Module Federation
32
+ *
33
+ * @param global - can be a global variable name OR connection string "global@url"
34
+ */
35
+ function useMFRemote(global) {
36
+ var remote;
37
+ if (isBrowser) {
38
+ // on client (we get instances from global variable because webpack breaks Singletons)
39
+ var MFClient_1 = window.mf_client;
40
+ remote = MFClient_1.remotes[global] || MFClient_1.registerRemote(global);
41
+ }
42
+ else {
43
+ // on server side
44
+ remote = RemoteContainer.RemoteContainer.createSingleton(global);
45
+ }
46
+ var _a = _tslib.__read(React__namespace.useState(remote.isLoaded()), 2), loaded = _a[0], setLoaded = _a[1];
47
+ var _b = _tslib.__read(React__namespace.useState(remote.error), 2), error = _b[0], setError = _b[1];
48
+ React__namespace.useEffect(function () {
49
+ var handleLoadComplete = function () {
50
+ setLoaded(true);
51
+ };
52
+ var handleLoadError = function (e) {
53
+ setError(e);
54
+ };
55
+ if (!loaded && remote.isLoaded()) {
56
+ handleLoadComplete();
57
+ }
58
+ remote.events.on('loadComplete', handleLoadComplete);
59
+ remote.events.on('loadError', handleLoadError);
60
+ return function () {
61
+ remote.events.off('loadComplete', handleLoadComplete);
62
+ remote.events.off('loadError', handleLoadError);
63
+ };
64
+ }, [remote]);
65
+ return {
66
+ remote: remote,
67
+ loaded: loaded,
68
+ error: error,
69
+ };
70
+ }
71
+
72
+ exports.useMFRemote = useMFRemote;
@@ -0,0 +1,215 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ /**
6
+ * 🛑🛑🛑 Attention! 🛑🛑🛑
7
+ * Do not add type definitions to this file!!
8
+ * It already exists in src/client folder.
9
+ * So remove this file and import ts version from src/client/UrlNode.
10
+ *
11
+ * This file was add just for proper compilation of JS files without any rollup warnings:
12
+ * "(!) Unresolved dependencies"
13
+ * "nextjs-mf/src/client/UrlNode (imported by nextjs-mf/src/client/UrlNode?commonjs-external)"
14
+ */
15
+
16
+ /**
17
+ * This class provides a logic of sorting dynamic routes in NextJS.
18
+ *
19
+ * It was copied from
20
+ * @see https://github.com/vercel/next.js/blob/canary/packages/next/shared/lib/router/utils/sorted-routes.ts
21
+ */
22
+ class UrlNode {
23
+ placeholder = true;
24
+ children = new Map();
25
+ slugName = null;
26
+ restSlugName = null;
27
+ optionalRestSlugName = null;
28
+
29
+ insert(urlPath) {
30
+ this._insert(urlPath.split('/').filter(Boolean), [], false);
31
+ }
32
+
33
+ smoosh() {
34
+ return this._smoosh();
35
+ }
36
+
37
+ _smoosh(prefix = '/') {
38
+ const childrenPaths = [...this.children.keys()].sort();
39
+ if (this.slugName !== null) {
40
+ childrenPaths.splice(childrenPaths.indexOf('[]'), 1);
41
+ }
42
+ if (this.restSlugName !== null) {
43
+ childrenPaths.splice(childrenPaths.indexOf('[...]'), 1);
44
+ }
45
+ if (this.optionalRestSlugName !== null) {
46
+ childrenPaths.splice(childrenPaths.indexOf('[[...]]'), 1);
47
+ }
48
+
49
+ const routes = childrenPaths
50
+ .map((c) => this.children.get(c)._smoosh(`${prefix}${c}/`))
51
+ .reduce((prev, curr) => [...prev, ...curr], []);
52
+
53
+ if (this.slugName !== null) {
54
+ routes.push(
55
+ ...this.children.get('[]')._smoosh(`${prefix}[${this.slugName}]/`)
56
+ );
57
+ }
58
+
59
+ if (!this.placeholder) {
60
+ const r = prefix === '/' ? '/' : prefix.slice(0, -1);
61
+ if (this.optionalRestSlugName != null) {
62
+ throw new Error(
63
+ `You cannot define a route with the same specificity as a optional catch-all route ("${r}" and "${r}[[...${this.optionalRestSlugName}]]").`
64
+ );
65
+ }
66
+
67
+ routes.unshift(r);
68
+ }
69
+
70
+ if (this.restSlugName !== null) {
71
+ routes.push(
72
+ ...this.children
73
+ .get('[...]')
74
+ ._smoosh(`${prefix}[...${this.restSlugName}]/`)
75
+ );
76
+ }
77
+
78
+ if (this.optionalRestSlugName !== null) {
79
+ routes.push(
80
+ ...this.children
81
+ .get('[[...]]')
82
+ ._smoosh(`${prefix}[[...${this.optionalRestSlugName}]]/`)
83
+ );
84
+ }
85
+
86
+ return routes;
87
+ }
88
+
89
+ _insert(urlPaths, slugNames, isCatchAll) {
90
+ if (urlPaths.length === 0) {
91
+ this.placeholder = false;
92
+ return;
93
+ }
94
+
95
+ if (isCatchAll) {
96
+ throw new Error(`Catch-all must be the last part of the URL.`);
97
+ }
98
+
99
+ // The next segment in the urlPaths list
100
+ let nextSegment = urlPaths[0];
101
+
102
+ // Check if the segment matches `[something]`
103
+ if (nextSegment.startsWith('[') && nextSegment.endsWith(']')) {
104
+ // Strip `[` and `]`, leaving only `something`
105
+ let segmentName = nextSegment.slice(1, -1);
106
+
107
+ let isOptional = false;
108
+ if (segmentName.startsWith('[') && segmentName.endsWith(']')) {
109
+ // Strip optional `[` and `]`, leaving only `something`
110
+ segmentName = segmentName.slice(1, -1);
111
+ isOptional = true;
112
+ }
113
+
114
+ if (segmentName.startsWith('...')) {
115
+ // Strip `...`, leaving only `something`
116
+ segmentName = segmentName.substring(3);
117
+ isCatchAll = true;
118
+ }
119
+
120
+ if (segmentName.startsWith('[') || segmentName.endsWith(']')) {
121
+ throw new Error(
122
+ `Segment names may not start or end with extra brackets ('${segmentName}').`
123
+ );
124
+ }
125
+
126
+ if (segmentName.startsWith('.')) {
127
+ throw new Error(
128
+ `Segment names may not start with erroneous periods ('${segmentName}').`
129
+ );
130
+ }
131
+
132
+ const handleSlug = function handleSlug(previousSlug, nextSlug) {
133
+ if (previousSlug !== null) {
134
+ // If the specific segment already has a slug but the slug is not `something`
135
+ // This prevents collisions like:
136
+ // pages/[post]/index.js
137
+ // pages/[id]/index.js
138
+ // Because currently multiple dynamic params on the same segment level are not supported
139
+ if (previousSlug !== nextSlug) {
140
+ // TODO: This error seems to be confusing for users, needs an error link, the description can be based on above comment.
141
+ throw new Error(
142
+ `You cannot use different slug names for the same dynamic path ('${previousSlug}' !== '${nextSlug}').`
143
+ );
144
+ }
145
+ }
146
+
147
+ slugNames.forEach((slug) => {
148
+ if (slug === nextSlug) {
149
+ throw new Error(
150
+ `You cannot have the same slug name "${nextSlug}" repeat within a single dynamic path`
151
+ );
152
+ }
153
+
154
+ if (slug.replace(/\W/g, '') === nextSegment.replace(/\W/g, '')) {
155
+ throw new Error(
156
+ `You cannot have the slug names "${slug}" and "${nextSlug}" differ only by non-word symbols within a single dynamic path`
157
+ );
158
+ }
159
+ });
160
+
161
+ slugNames.push(nextSlug);
162
+ };
163
+
164
+ if (isCatchAll) {
165
+ if (isOptional) {
166
+ if (this.restSlugName != null) {
167
+ throw new Error(
168
+ `You cannot use both an required and optional catch-all route at the same level ("[...${this.restSlugName}]" and "${urlPaths[0]}" ).`
169
+ );
170
+ }
171
+
172
+ handleSlug(this.optionalRestSlugName, segmentName);
173
+ // slugName is kept as it can only be one particular slugName
174
+ this.optionalRestSlugName = segmentName;
175
+ // nextSegment is overwritten to [[...]] so that it can later be sorted specifically
176
+ nextSegment = '[[...]]';
177
+ } else {
178
+ if (this.optionalRestSlugName != null) {
179
+ throw new Error(
180
+ `You cannot use both an optional and required catch-all route at the same level ("[[...${this.optionalRestSlugName}]]" and "${urlPaths[0]}").`
181
+ );
182
+ }
183
+
184
+ handleSlug(this.restSlugName, segmentName);
185
+ // slugName is kept as it can only be one particular slugName
186
+ this.restSlugName = segmentName;
187
+ // nextSegment is overwritten to [...] so that it can later be sorted specifically
188
+ nextSegment = '[...]';
189
+ }
190
+ } else {
191
+ if (isOptional) {
192
+ throw new Error(
193
+ `Optional route parameters are not yet supported ("${urlPaths[0]}").`
194
+ );
195
+ }
196
+ handleSlug(this.slugName, segmentName);
197
+ // slugName is kept as it can only be one particular slugName
198
+ this.slugName = segmentName;
199
+ // nextSegment is overwritten to [] so that it can later be sorted specifically
200
+ nextSegment = '[]';
201
+ }
202
+ }
203
+
204
+ // If this UrlNode doesn't have the nextSegment yet we create a new child UrlNode
205
+ if (!this.children.has(nextSegment)) {
206
+ this.children.set(nextSegment, new UrlNode());
207
+ }
208
+
209
+ this.children
210
+ .get(nextSegment)
211
+ ._insert(urlPaths.slice(1), slugNames, isCatchAll);
212
+ }
213
+ }
214
+
215
+ exports.UrlNode = UrlNode;
@@ -1,8 +1,13 @@
1
+ 'use strict';
2
+
3
+ var helpers = require('../_virtual/helpers.js');
4
+
1
5
  /**
2
6
  * Inject a loader into the current module rule.
3
7
  * This function mutates `rule` argument!
4
8
  */
5
- module.exports.injectRuleLoader = function injectRuleLoader(rule, loader) {
9
+
10
+ helpers.__exports.injectRuleLoader = function injectRuleLoader(rule, loader) {
6
11
  if (rule.loader) {
7
12
  rule.use = [loader, { loader: rule.loader, options: rule.options }];
8
13
  delete rule.loader;
@@ -15,7 +20,7 @@ module.exports.injectRuleLoader = function injectRuleLoader(rule, loader) {
15
20
  /**
16
21
  * Check that current module rule has a loader with the provided name.
17
22
  */
18
- module.exports.hasLoader = function hasLoader(rule, loaderName) {
23
+ helpers.__exports.hasLoader = function hasLoader(rule, loaderName) {
19
24
  if (rule.loader === loaderName) {
20
25
  return true;
21
26
  } else if (rule.use) {
@@ -34,7 +39,7 @@ module.exports.hasLoader = function hasLoader(rule, loaderName) {
34
39
  return false;
35
40
  };
36
41
 
37
- module.exports.toDisplayErrors = function toDisplayErrors(err) {
42
+ helpers.__exports.toDisplayErrors = function toDisplayErrors(err) {
38
43
  return err
39
44
  .map((error) => {
40
45
  let message = error.message;
@@ -45,3 +50,5 @@ module.exports.toDisplayErrors = function toDisplayErrors(err) {
45
50
  })
46
51
  .join('\n');
47
52
  };
53
+
54
+ module.exports = helpers.__exports;