@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,161 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _tslib = require('../_virtual/_tslib.js');
6
+ var EventEmitter = require('eventemitter3');
7
+ var utils = require('../utils.js');
8
+
9
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
+
11
+ var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
12
+
13
+ /**
14
+ * This is a Lazy loader of webpack remote container with some NextJS-specific helper methods.
15
+ *
16
+ * It provides the ability to register remote, and load & init it on the first use.
17
+ */
18
+ var RemoteContainer = /** @class */ (function () {
19
+ function RemoteContainer(opts) {
20
+ this.global = opts.global;
21
+ this.url = opts.url;
22
+ this.events = new EventEmitter__default["default"]();
23
+ }
24
+ /**
25
+ * Create or reuse existed remote entry.
26
+ *
27
+ * Be careful, Singleton pattern does not work well in webpack builds,
28
+ * because one module may be copied between different chunks. In such a way
29
+ * you obtain several lists of instances.
30
+ */
31
+ RemoteContainer.createSingleton = function (remote) {
32
+ var data;
33
+ if (typeof remote === 'string') {
34
+ var _a = _tslib.__read(remote.split('@'), 2), global_1 = _a[0], url = _a[1];
35
+ data = { global: global_1, url: url };
36
+ }
37
+ else if ((remote === null || remote === void 0 ? void 0 : remote.global) && (remote === null || remote === void 0 ? void 0 : remote.url)) {
38
+ data = { global: remote.global, url: remote.url };
39
+ }
40
+ if (!data) {
41
+ console.error("Cannot init RemoteContainer with following data", RemoteContainer);
42
+ throw Error('[nextjs-mf] RemoteContainer.createSingleton(remote) accepts string "shop@http://example.com/_next/static/chunks/remoteEntry.js" OR object { global: "shop", url: "http://example.com/_next/static/chunks/remoteEntry.js"}');
43
+ }
44
+ var container;
45
+ if (this.instances[data.global]) {
46
+ container = this.instances[data.global];
47
+ }
48
+ else {
49
+ container = new RemoteContainer(data);
50
+ this.instances[data.global] = container;
51
+ }
52
+ return container;
53
+ };
54
+ /**
55
+ * Check is the current remoteEntry.js loaded or not
56
+ */
57
+ RemoteContainer.prototype.isLoaded = function () {
58
+ return !!this.container;
59
+ };
60
+ /**
61
+ * Returns initialized webpack RemoteContainer.
62
+ * If its' script does not loaded - then load & init it firstly.
63
+ */
64
+ RemoteContainer.prototype.getContainer = function () {
65
+ return _tslib.__awaiter(this, void 0, void 0, function () {
66
+ var container, e_1;
67
+ return _tslib.__generator(this, function (_a) {
68
+ switch (_a.label) {
69
+ case 0:
70
+ if (this.container) {
71
+ return [2 /*return*/, this.container];
72
+ }
73
+ this.events.emit('loadStart', this);
74
+ _a.label = 1;
75
+ case 1:
76
+ _a.trys.push([1, 3, , 4]);
77
+ return [4 /*yield*/, utils.injectScript({
78
+ global: this.global,
79
+ url: this.url,
80
+ })];
81
+ case 2:
82
+ container = _a.sent();
83
+ if (container) {
84
+ this.container = container;
85
+ this.events.emit('loadComplete', this);
86
+ return [2 /*return*/, container];
87
+ }
88
+ throw Error("[nextjs-mf] Remote container ".concat(this.url, " is empty"));
89
+ case 3:
90
+ e_1 = _a.sent();
91
+ this.error = e_1;
92
+ this.events.emit('loadError', e_1.message, this);
93
+ throw e_1;
94
+ case 4: return [2 /*return*/];
95
+ }
96
+ });
97
+ });
98
+ };
99
+ /**
100
+ * Return remote module from container.
101
+ * If you provide `exportName` it automatically return exact property value from module.
102
+ *
103
+ * @example
104
+ * remote.getModule('./pages/index', 'default')
105
+ */
106
+ RemoteContainer.prototype.getModule = function (modulePath, exportName) {
107
+ return _tslib.__awaiter(this, void 0, void 0, function () {
108
+ var container, modFactory, mod;
109
+ return _tslib.__generator(this, function (_a) {
110
+ switch (_a.label) {
111
+ case 0: return [4 /*yield*/, this.getContainer()];
112
+ case 1:
113
+ container = _a.sent();
114
+ return [4 /*yield*/, container.get(modulePath)];
115
+ case 2:
116
+ modFactory = _a.sent();
117
+ if (!modFactory)
118
+ return [2 /*return*/, undefined];
119
+ mod = modFactory();
120
+ if (exportName) {
121
+ return [2 /*return*/, mod && typeof mod === 'object' ? mod[exportName] : undefined];
122
+ }
123
+ else {
124
+ return [2 /*return*/, mod];
125
+ }
126
+ }
127
+ });
128
+ });
129
+ };
130
+ /**
131
+ * Retrieve registered nextjs' routes from remote app
132
+ */
133
+ RemoteContainer.prototype.getPageMap = function () {
134
+ return _tslib.__awaiter(this, void 0, void 0, function () {
135
+ var pageMap;
136
+ return _tslib.__generator(this, function (_a) {
137
+ switch (_a.label) {
138
+ case 0:
139
+ if (this.pageMap) {
140
+ return [2 /*return*/, this.pageMap];
141
+ }
142
+ return [4 /*yield*/, this.getModule('./pages-map-v2', 'default')];
143
+ case 1:
144
+ pageMap = _a.sent();
145
+ if (pageMap) {
146
+ this.pageMap = pageMap;
147
+ }
148
+ else {
149
+ this.pageMap = {};
150
+ console.warn("[nextjs-mf] Container ".concat(this.global, " does not expose \"./pages-map-v2\" module."));
151
+ }
152
+ return [2 /*return*/, this.pageMap];
153
+ }
154
+ });
155
+ });
156
+ };
157
+ RemoteContainer.instances = {};
158
+ return RemoteContainer;
159
+ }());
160
+
161
+ exports.RemoteContainer = RemoteContainer;
@@ -0,0 +1,48 @@
1
+ import { PageMap, RemoteContainer } from './RemoteContainer';
2
+ export declare type PathPrefix = string;
3
+ export declare type RemoteToRoutes = Map<RemoteContainer, PathPrefix | PathPrefix[]>;
4
+ export declare type RouteInfo = {
5
+ component: any;
6
+ exports: any;
7
+ styles: string[];
8
+ };
9
+ /**
10
+ * A class which prepares/loads a list of remotes pages and knows how
11
+ * to prepare NextJS pseudo-module of route data.
12
+ */
13
+ export declare class RemotePages {
14
+ paths: Record<PathPrefix, RemoteContainer>;
15
+ pageListCache: string[] | undefined;
16
+ private asyncLoadedPageMaps;
17
+ constructor(remoteToRoutes?: RemoteToRoutes);
18
+ /**
19
+ * Add remote routes for specific RemoteContainer which serves them.
20
+ */
21
+ addRoutes(routes: string | string[], remote: RemoteContainer): void;
22
+ /**
23
+ * Load a remote page map and add its routes to registry.
24
+ */
25
+ loadRemotePageMap(remote: RemoteContainer): Promise<PageMap | undefined>;
26
+ /**
27
+ * Get remote module according to provided next route.
28
+ * Under the hood it automatically determines which remote need to be used.
29
+ */
30
+ routeToPageModule(route: string): Promise<any>;
31
+ /**
32
+ * Check that provided route present in registry.
33
+ */
34
+ hasRoute(route: string): boolean;
35
+ /**
36
+ * Find remote according to provided route.
37
+ */
38
+ routeToRemote(route: string): RemoteContainer | undefined;
39
+ /**
40
+ * Get cached unsorted list of remote routes.
41
+ */
42
+ getPageList(): string[];
43
+ /**
44
+ * Get prepared pseudo-module which is consumed by Nextjs' router.
45
+ */
46
+ getRouteInfo(route: string): Promise<undefined | RouteInfo>;
47
+ }
48
+ //# sourceMappingURL=RemotePages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RemotePages.d.ts","sourceRoot":"","sources":["../../src/client/RemotePages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE7D,oBAAY,UAAU,GAAG,MAAM,CAAC;AAEhC,oBAAY,cAAc,GAAG,GAAG,CAAC,eAAe,EAAE,UAAU,GAAG,UAAU,EAAE,CAAC,CAAC;AAE7E,oBAAY,SAAS,GAAG;IACtB,SAAS,EAAE,GAAG,CAAC;IACf,OAAO,EAAE,GAAG,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,qBAAa,WAAW;IACtB,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC,CAAM;IAChD,aAAa,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACpC,OAAO,CAAC,mBAAmB,CAAuB;gBAEtC,cAAc,CAAC,EAAE,cAAc;IAQ3C;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,MAAM,EAAE,eAAe;IAW5D;;OAEG;IACG,iBAAiB,CACrB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAc/B;;;OAGG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM;IAmBrC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIhC;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAsBzD;;OAEG;IACH,WAAW;IAQX;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CAuBlE"}
@@ -0,0 +1,168 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _tslib = require('../_virtual/_tslib.js');
6
+
7
+ /**
8
+ * A class which prepares/loads a list of remotes pages and knows how
9
+ * to prepare NextJS pseudo-module of route data.
10
+ */
11
+ var RemotePages = /** @class */ (function () {
12
+ function RemotePages(remoteToRoutes) {
13
+ var _this = this;
14
+ this.paths = {};
15
+ this.asyncLoadedPageMaps = new Set();
16
+ this.pageListCache = undefined;
17
+ remoteToRoutes === null || remoteToRoutes === void 0 ? void 0 : remoteToRoutes.forEach(function (routes, remote) {
18
+ _this.addRoutes(routes, remote);
19
+ });
20
+ }
21
+ /**
22
+ * Add remote routes for specific RemoteContainer which serves them.
23
+ */
24
+ RemotePages.prototype.addRoutes = function (routes, remote) {
25
+ var _this = this;
26
+ if (Array.isArray(routes)) {
27
+ routes.forEach(function (route) {
28
+ _this.paths[route] = remote;
29
+ });
30
+ }
31
+ else {
32
+ this.paths[routes] = remote;
33
+ }
34
+ this.pageListCache = Object.keys(this.paths);
35
+ };
36
+ /**
37
+ * Load a remote page map and add its routes to registry.
38
+ */
39
+ RemotePages.prototype.loadRemotePageMap = function (remote) {
40
+ return _tslib.__awaiter(this, void 0, void 0, function () {
41
+ var pageMap;
42
+ return _tslib.__generator(this, function (_a) {
43
+ switch (_a.label) {
44
+ case 0: return [4 /*yield*/, remote.getPageMap()];
45
+ case 1:
46
+ pageMap = _a.sent();
47
+ if (!pageMap)
48
+ return [2 /*return*/, undefined];
49
+ // init once page map from remote if it wasn't done before
50
+ // here we updating real routes received from remote app in runtime
51
+ if (!this.asyncLoadedPageMaps.has(remote)) {
52
+ this.asyncLoadedPageMaps.add(remote);
53
+ this.addRoutes(Object.keys(pageMap), remote);
54
+ }
55
+ return [2 /*return*/, pageMap];
56
+ }
57
+ });
58
+ });
59
+ };
60
+ /**
61
+ * Get remote module according to provided next route.
62
+ * Under the hood it automatically determines which remote need to be used.
63
+ */
64
+ RemotePages.prototype.routeToPageModule = function (route) {
65
+ return _tslib.__awaiter(this, void 0, void 0, function () {
66
+ var remote, pageMap, modulePath;
67
+ return _tslib.__generator(this, function (_a) {
68
+ switch (_a.label) {
69
+ case 0:
70
+ remote = this.routeToRemote(route);
71
+ if (!remote) {
72
+ return [2 /*return*/, undefined];
73
+ }
74
+ return [4 /*yield*/, this.loadRemotePageMap(remote)];
75
+ case 1:
76
+ pageMap = _a.sent();
77
+ if (!pageMap) {
78
+ return [2 /*return*/, undefined];
79
+ }
80
+ modulePath = pageMap[route];
81
+ if (!modulePath) {
82
+ return [2 /*return*/, undefined];
83
+ }
84
+ return [2 /*return*/, remote.getModule(modulePath)];
85
+ }
86
+ });
87
+ });
88
+ };
89
+ /**
90
+ * Check that provided route present in registry.
91
+ */
92
+ RemotePages.prototype.hasRoute = function (route) {
93
+ var _a;
94
+ return !!((_a = this.pageListCache) === null || _a === void 0 ? void 0 : _a.includes(route));
95
+ };
96
+ /**
97
+ * Find remote according to provided route.
98
+ */
99
+ RemotePages.prototype.routeToRemote = function (route) {
100
+ var bestMatch;
101
+ for (var basepath in this.paths) {
102
+ if (route === basepath) {
103
+ return this.paths[basepath];
104
+ }
105
+ else if (route.startsWith("".concat(basepath, "/"))) {
106
+ if (!bestMatch) {
107
+ bestMatch = basepath;
108
+ }
109
+ else if (bestMatch.length < basepath.length) {
110
+ bestMatch = basepath;
111
+ }
112
+ }
113
+ }
114
+ if (bestMatch) {
115
+ return this.paths[bestMatch];
116
+ }
117
+ return undefined;
118
+ };
119
+ /**
120
+ * Get cached unsorted list of remote routes.
121
+ */
122
+ RemotePages.prototype.getPageList = function () {
123
+ // it's very important to return the same Array instance
124
+ // because it instance is used in CombinedPages for recalculation of sorted version of all routes
125
+ var pageList = this.pageListCache || Object.keys(this.paths);
126
+ this.pageListCache = pageList;
127
+ return pageList;
128
+ };
129
+ /**
130
+ * Get prepared pseudo-module which is consumed by Nextjs' router.
131
+ */
132
+ RemotePages.prototype.getRouteInfo = function (route) {
133
+ return _tslib.__awaiter(this, void 0, void 0, function () {
134
+ var routeInfo, mod, e_1;
135
+ return _tslib.__generator(this, function (_a) {
136
+ switch (_a.label) {
137
+ case 0:
138
+ _a.trys.push([0, 2, , 3]);
139
+ return [4 /*yield*/, this.routeToPageModule(route)];
140
+ case 1:
141
+ mod = _a.sent();
142
+ if (mod) {
143
+ routeInfo = {
144
+ component: mod.default,
145
+ exports: mod,
146
+ styles: [],
147
+ };
148
+ }
149
+ return [3 /*break*/, 3];
150
+ case 2:
151
+ e_1 = _a.sent();
152
+ routeInfo = {
153
+ // TODO: provide ability to customize component with Error
154
+ component: function () { return e_1.message; },
155
+ exports: {},
156
+ styles: [],
157
+ };
158
+ console.warn(e_1);
159
+ return [3 /*break*/, 3];
160
+ case 3: return [2 /*return*/, routeInfo];
161
+ }
162
+ });
163
+ });
164
+ };
165
+ return RemotePages;
166
+ }());
167
+
168
+ exports.RemotePages = RemotePages;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * This class provides a logic of sorting dynamic routes in NextJS.
3
+ *
4
+ * It was copied from
5
+ * @see https://github.com/vercel/next.js/blob/canary/packages/next/shared/lib/router/utils/sorted-routes.ts
6
+ */
7
+ export declare class UrlNode {
8
+ placeholder: boolean;
9
+ children: Map<string, UrlNode>;
10
+ slugName: string | null;
11
+ restSlugName: string | null;
12
+ optionalRestSlugName: string | null;
13
+ insert(urlPath: string): void;
14
+ smoosh(): string[];
15
+ private _smoosh;
16
+ private _insert;
17
+ }
18
+ //# sourceMappingURL=UrlNode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UrlNode.d.ts","sourceRoot":"","sources":["../../src/client/UrlNode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,OAAO;IAClB,WAAW,EAAE,OAAO,CAAQ;IAC5B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAa;IAC3C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC/B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE3C,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI7B,MAAM,IAAI,MAAM,EAAE;IAIlB,OAAO,CAAC,OAAO;IAoDf,OAAO,CAAC,OAAO;CAmIhB"}
@@ -0,0 +1,162 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _tslib = require('../_virtual/_tslib.js');
6
+
7
+ /**
8
+ * This class provides a logic of sorting dynamic routes in NextJS.
9
+ *
10
+ * It was copied from
11
+ * @see https://github.com/vercel/next.js/blob/canary/packages/next/shared/lib/router/utils/sorted-routes.ts
12
+ */
13
+ var UrlNode = /** @class */ (function () {
14
+ function UrlNode() {
15
+ this.placeholder = true;
16
+ this.children = new Map();
17
+ this.slugName = null;
18
+ this.restSlugName = null;
19
+ this.optionalRestSlugName = null;
20
+ }
21
+ UrlNode.prototype.insert = function (urlPath) {
22
+ this._insert(urlPath.split('/').filter(Boolean), [], false);
23
+ };
24
+ UrlNode.prototype.smoosh = function () {
25
+ return this._smoosh();
26
+ };
27
+ UrlNode.prototype._smoosh = function (prefix) {
28
+ var _this = this;
29
+ if (prefix === void 0) { prefix = '/'; }
30
+ var childrenPaths = _tslib.__spreadArray([], _tslib.__read(this.children.keys()), false).sort();
31
+ if (this.slugName !== null) {
32
+ childrenPaths.splice(childrenPaths.indexOf('[]'), 1);
33
+ }
34
+ if (this.restSlugName !== null) {
35
+ childrenPaths.splice(childrenPaths.indexOf('[...]'), 1);
36
+ }
37
+ if (this.optionalRestSlugName !== null) {
38
+ childrenPaths.splice(childrenPaths.indexOf('[[...]]'), 1);
39
+ }
40
+ var routes = childrenPaths
41
+ .map(function (c) { return _this.children.get(c)._smoosh("".concat(prefix).concat(c, "/")); })
42
+ .reduce(function (prev, curr) { return _tslib.__spreadArray(_tslib.__spreadArray([], _tslib.__read(prev), false), _tslib.__read(curr), false); }, []);
43
+ if (this.slugName !== null) {
44
+ routes.push.apply(routes, _tslib.__spreadArray([], _tslib.__read(this.children.get('[]')._smoosh("".concat(prefix, "[").concat(this.slugName, "]/"))), false));
45
+ }
46
+ if (!this.placeholder) {
47
+ var r = prefix === '/' ? '/' : prefix.slice(0, -1);
48
+ if (this.optionalRestSlugName != null) {
49
+ throw new Error("You cannot define a route with the same specificity as a optional catch-all route (\"".concat(r, "\" and \"").concat(r, "[[...").concat(this.optionalRestSlugName, "]]\")."));
50
+ }
51
+ routes.unshift(r);
52
+ }
53
+ if (this.restSlugName !== null) {
54
+ routes.push.apply(routes, _tslib.__spreadArray([], _tslib.__read(this.children
55
+ .get('[...]')
56
+ ._smoosh("".concat(prefix, "[...").concat(this.restSlugName, "]/"))), false));
57
+ }
58
+ if (this.optionalRestSlugName !== null) {
59
+ routes.push.apply(routes, _tslib.__spreadArray([], _tslib.__read(this.children
60
+ .get('[[...]]')
61
+ ._smoosh("".concat(prefix, "[[...").concat(this.optionalRestSlugName, "]]/"))), false));
62
+ }
63
+ return routes;
64
+ };
65
+ UrlNode.prototype._insert = function (urlPaths, slugNames, isCatchAll) {
66
+ if (urlPaths.length === 0) {
67
+ this.placeholder = false;
68
+ return;
69
+ }
70
+ if (isCatchAll) {
71
+ throw new Error("Catch-all must be the last part of the URL.");
72
+ }
73
+ // The next segment in the urlPaths list
74
+ var nextSegment = urlPaths[0];
75
+ // Check if the segment matches `[something]`
76
+ if (nextSegment.startsWith('[') && nextSegment.endsWith(']')) {
77
+ // Strip `[` and `]`, leaving only `something`
78
+ var segmentName = nextSegment.slice(1, -1);
79
+ var isOptional = false;
80
+ if (segmentName.startsWith('[') && segmentName.endsWith(']')) {
81
+ // Strip optional `[` and `]`, leaving only `something`
82
+ segmentName = segmentName.slice(1, -1);
83
+ isOptional = true;
84
+ }
85
+ if (segmentName.startsWith('...')) {
86
+ // Strip `...`, leaving only `something`
87
+ segmentName = segmentName.substring(3);
88
+ isCatchAll = true;
89
+ }
90
+ if (segmentName.startsWith('[') || segmentName.endsWith(']')) {
91
+ throw new Error("Segment names may not start or end with extra brackets ('".concat(segmentName, "')."));
92
+ }
93
+ if (segmentName.startsWith('.')) {
94
+ throw new Error("Segment names may not start with erroneous periods ('".concat(segmentName, "')."));
95
+ }
96
+ var handleSlug = function handleSlug(previousSlug, nextSlug) {
97
+ if (previousSlug !== null) {
98
+ // If the specific segment already has a slug but the slug is not `something`
99
+ // This prevents collisions like:
100
+ // pages/[post]/index.js
101
+ // pages/[id]/index.js
102
+ // Because currently multiple dynamic params on the same segment level are not supported
103
+ if (previousSlug !== nextSlug) {
104
+ // TODO: This error seems to be confusing for users, needs an error link, the description can be based on above comment.
105
+ throw new Error("You cannot use different slug names for the same dynamic path ('".concat(previousSlug, "' !== '").concat(nextSlug, "')."));
106
+ }
107
+ }
108
+ slugNames.forEach(function (slug) {
109
+ if (slug === nextSlug) {
110
+ throw new Error("You cannot have the same slug name \"".concat(nextSlug, "\" repeat within a single dynamic path"));
111
+ }
112
+ if (slug.replace(/\W/g, '') === nextSegment.replace(/\W/g, '')) {
113
+ throw new Error("You cannot have the slug names \"".concat(slug, "\" and \"").concat(nextSlug, "\" differ only by non-word symbols within a single dynamic path"));
114
+ }
115
+ });
116
+ slugNames.push(nextSlug);
117
+ };
118
+ if (isCatchAll) {
119
+ if (isOptional) {
120
+ if (this.restSlugName != null) {
121
+ throw new Error("You cannot use both an required and optional catch-all route at the same level (\"[...".concat(this.restSlugName, "]\" and \"").concat(urlPaths[0], "\" )."));
122
+ }
123
+ handleSlug(this.optionalRestSlugName, segmentName);
124
+ // slugName is kept as it can only be one particular slugName
125
+ this.optionalRestSlugName = segmentName;
126
+ // nextSegment is overwritten to [[...]] so that it can later be sorted specifically
127
+ nextSegment = '[[...]]';
128
+ }
129
+ else {
130
+ if (this.optionalRestSlugName != null) {
131
+ throw new Error("You cannot use both an optional and required catch-all route at the same level (\"[[...".concat(this.optionalRestSlugName, "]]\" and \"").concat(urlPaths[0], "\")."));
132
+ }
133
+ handleSlug(this.restSlugName, segmentName);
134
+ // slugName is kept as it can only be one particular slugName
135
+ this.restSlugName = segmentName;
136
+ // nextSegment is overwritten to [...] so that it can later be sorted specifically
137
+ nextSegment = '[...]';
138
+ }
139
+ }
140
+ else {
141
+ if (isOptional) {
142
+ throw new Error("Optional route parameters are not yet supported (\"".concat(urlPaths[0], "\")."));
143
+ }
144
+ handleSlug(this.slugName, segmentName);
145
+ // slugName is kept as it can only be one particular slugName
146
+ this.slugName = segmentName;
147
+ // nextSegment is overwritten to [] so that it can later be sorted specifically
148
+ nextSegment = '[]';
149
+ }
150
+ }
151
+ // If this UrlNode doesn't have the nextSegment yet we create a new child UrlNode
152
+ if (!this.children.has(nextSegment)) {
153
+ this.children.set(nextSegment, new UrlNode());
154
+ }
155
+ this.children
156
+ .get(nextSegment)
157
+ ._insert(urlPaths.slice(1), slugNames, isCatchAll);
158
+ };
159
+ return UrlNode;
160
+ }());
161
+
162
+ exports.UrlNode = UrlNode;
@@ -0,0 +1,17 @@
1
+ export declare function isDynamicRoute(route: string): boolean;
2
+ export declare function getRouteRegex(normalizedRoute: string): {
3
+ re: RegExp;
4
+ groups: {};
5
+ };
6
+ /**
7
+ * Convert browser pathname to NextJs route.
8
+ * This method is required for proper work of Dynamic routes in NextJS.
9
+ */
10
+ export declare function pathnameToRoute(cleanPathname: string, routes: string[]): string | undefined;
11
+ /**
12
+ * Sort provided pages in correct nextjs order.
13
+ * This sorting is required if you are using dynamic routes in your apps.
14
+ * If order is incorrect then Nextjs may use dynamicRoute instead of exact page.
15
+ */
16
+ export declare function sortNextPages(pages: string[]): string[];
17
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/client/helpers.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,WAE3C;AA4CD,wBAAgB,aAAa,CAAC,eAAe,EAAE,MAAM;;;EAMpD;AAYD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EAAE,GACf,MAAM,GAAG,SAAS,CAYpB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAKvD"}