recreateRoute.tsx 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import type {PlainRoute} from 'react-router';
  2. import type {Location} from 'history';
  3. import replaceRouterParams from 'sentry/utils/replaceRouterParams';
  4. type Options = {
  5. // parameters to replace any route string parameters (e.g. if route is `:orgId`,
  6. // params should have `{orgId: slug}`
  7. params: {[key: string]: string | undefined};
  8. routes: PlainRoute[];
  9. location?: Location;
  10. /**
  11. * The number of routes to to pop off of `routes
  12. * Must be < 0
  13. *
  14. * There's no ts type for negative numbers so we are arbitrarily specifying -1-9
  15. */
  16. stepBack?: -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8 | -9;
  17. };
  18. /**
  19. * Given a route object or a string and a list of routes + params from router, this will attempt to recreate a location string while replacing url params.
  20. * Can additionally specify the number of routes to move back
  21. *
  22. * See tests for examples
  23. */
  24. export default function recreateRoute(to: string | PlainRoute, options: Options): string {
  25. const {routes, params, location, stepBack} = options;
  26. const paths = routes.map(({path}) => {
  27. path = path || '';
  28. if (path.length > 0 && !path.endsWith('/')) {
  29. path = `${path}/`;
  30. }
  31. return path;
  32. });
  33. let lastRootIndex: number;
  34. let routeIndex: number | undefined;
  35. // TODO(ts): typescript things
  36. if (typeof to !== 'string') {
  37. routeIndex = routes.indexOf(to) + 1;
  38. lastRootIndex = paths.slice(0, routeIndex).findLastIndex(path => path[0] === '/');
  39. } else {
  40. lastRootIndex = paths.findLastIndex(path => path[0] === '/');
  41. }
  42. let baseRoute = paths.slice(lastRootIndex, routeIndex);
  43. if (typeof stepBack !== 'undefined') {
  44. baseRoute = baseRoute.slice(0, stepBack);
  45. }
  46. const search = location?.search ?? '';
  47. const hash = location?.hash ?? '';
  48. const fullRoute = `${baseRoute.join('')}${
  49. typeof to !== 'string' ? '' : to
  50. }${search}${hash}`;
  51. return replaceRouterParams(fullRoute, params);
  52. }