Explicitly sort routes to reduce a chance of conflicts (#5020)

* Explicitly sort routes to reduce (avoid at all?) a chance of conflicts

* Sort routes by params count
This commit is contained in:
Levko Kravets 2020-07-03 21:11:39 +03:00 committed by GitHub
parent 74f206614f
commit 9c0450c84e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 45 additions and 25 deletions

View File

@ -264,7 +264,7 @@ routes.register(
routes.register(
"Alerts.View",
routeWithUserSession({
path: "/alerts/:alertId([0-9]+)",
path: "/alerts/:alertId",
title: "Alert",
render: pageProps => <Alert {...pageProps} mode={MODES.VIEW} />,
})
@ -272,7 +272,7 @@ routes.register(
routes.register(
"Alerts.Edit",
routeWithUserSession({
path: "/alerts/:alertId([0-9]+)/edit",
path: "/alerts/:alertId/edit",
title: "Alert",
render: pageProps => <Alert {...pageProps} mode={MODES.EDIT} />,
})

View File

@ -144,7 +144,7 @@ const EditDataSourcePage = wrapSettingsTab("DataSources.Edit", null, EditDataSou
routes.register(
"DataSources.Edit",
routeWithUserSession({
path: "/data_sources/:dataSourceId([0-9]+)",
path: "/data_sources/:dataSourceId",
title: "Data Sources",
render: pageProps => <EditDataSourcePage {...pageProps} />,
})

View File

@ -111,7 +111,7 @@ const EditDestinationPage = wrapSettingsTab("AlertDestinations.Edit", null, Edit
routes.register(
"AlertDestinations.Edit",
routeWithUserSession({
path: "/destinations/:destinationId([0-9]+)",
path: "/destinations/:destinationId",
title: "Alert Destinations",
render: pageProps => <EditDestinationPage {...pageProps} />,
})

View File

@ -246,7 +246,7 @@ const GroupDataSourcesPage = wrapSettingsTab(
routes.register(
"Groups.DataSources",
routeWithUserSession({
path: "/groups/:groupId([0-9]+)/data_sources",
path: "/groups/:groupId/data_sources",
title: "Group Data Sources",
render: pageProps => <GroupDataSourcesPage {...pageProps} currentPage="datasources" />,
})

View File

@ -209,7 +209,7 @@ const GroupMembersPage = wrapSettingsTab(
routes.register(
"Groups.Members",
routeWithUserSession({
path: "/groups/:groupId([0-9]+)",
path: "/groups/:groupId",
title: "Group Members",
render: pageProps => <GroupMembersPage {...pageProps} currentPage="users" />,
})

View File

@ -429,7 +429,7 @@ routes.register(
routes.register(
"Queries.Edit",
routeWithUserSession({
path: "/queries/:queryId([0-9]+)/source",
path: "/queries/:queryId/source",
render: pageProps => <QuerySourcePage {...pageProps} />,
bodyClass: "fixed-layout",
})

View File

@ -223,7 +223,7 @@ const QueryViewPage = wrapQueryPage(QueryView);
routes.register(
"Queries.View",
routeWithUserSession({
path: "/queries/:queryId([0-9]+)",
path: "/queries/:queryId",
render: pageProps => <QueryViewPage {...pageProps} />,
})
);

View File

@ -224,7 +224,7 @@ routes.register(
routes.register(
"QuerySnippets.NewOrEdit",
routeWithUserSession({
path: "/query_snippets/:querySnippetId(new|[0-9]+)",
path: "/query_snippets/:querySnippetId",
title: "Query Snippets",
render: pageProps => <QuerySnippetsListPage {...pageProps} currentPage="query_snippets" isNewOrEditPage />,
})

View File

@ -89,7 +89,7 @@ routes.register(
routes.register(
"Users.ViewOrEdit",
routeWithUserSession({
path: "/users/:userId([0-9]+)",
path: "/users/:userId",
title: "Users",
render: pageProps => <UserProfilePage {...pageProps} />,
})

View File

@ -1,19 +1,40 @@
import { isString, isObject, filter } from "lodash";
import { isString, isObject, filter, sortBy } from "lodash";
import pathToRegexp from "path-to-regexp";
function getRouteParamsCount(path) {
const tokens = pathToRegexp.parse(path);
return filter(tokens, isObject).length;
}
class Routes {
items = [];
_items = [];
_sorted = false;
get items() {
if (!this._sorted) {
this._items = sortBy(this._items, [
item => getRouteParamsCount(item.path), // simple definitions first, with more params - last
item => -item.path.length, // longer first
item => item.path, // if same type and length - sort alphabetically
]);
this._sorted = true;
}
return this._items;
}
register(id, route) {
id = isString(id) ? id : null;
this.unregister(id);
if (isObject(route)) {
this.items = [...this.items, { ...route, id }];
this._items = [...this._items, { ...route, id }];
this._sorted = false;
}
}
unregister(id) {
if (isString(id)) {
this.items = filter(this.items, item => item.id !== id);
// removing item does not break their order (if already sorted)
this._items = filter(this._items, item => item.id !== id);
}
}
}

20
package-lock.json generated
View File

@ -6206,6 +6206,12 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
"dev": true
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
@ -12088,10 +12094,9 @@
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
"dev": true
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz",
"integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA=="
},
"path-type": {
"version": "3.0.0",
@ -17084,13 +17089,6 @@
"integrity": "sha512-cBkihRoHvRQAjdUnDE1GGuuw/TPAIi8z2pEsSmUVAWLeZdgjHzzAb1+0VOO6NvBOvySItOTQikzaGlRxRdJBnA==",
"requires": {
"path-to-regexp": "^3.1.0"
},
"dependencies": {
"path-to-regexp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz",
"integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA=="
}
}
},
"universalify": {

View File

@ -64,6 +64,7 @@
"mousetrap": "^1.6.1",
"mustache": "^2.3.0",
"numeral": "^2.0.6",
"path-to-regexp": "^3.1.0",
"prop-types": "^15.6.1",
"query-string": "^6.9.0",
"react": "^16.8.3",