@backstage/core-app-api 1.0.6-next.0 → 1.1.0-next.1
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/CHANGELOG.md +13 -0
- package/dist/index.esm.js +184 -33
- package/dist/index.esm.js.map +1 -1
- package/package.json +12 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @backstage/core-app-api
|
|
2
2
|
|
|
3
|
+
## 1.1.0-next.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a448fea691: Updated the routing system to be compatible with React Router v6 stable.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 817f3196f6: Updated React Router dependencies to be peer dependencies.
|
|
12
|
+
- 70299c99d5: Updated `FlatRoutes` to be compatible with React Router v6 stable.
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
- @backstage/core-plugin-api@1.0.6-next.1
|
|
15
|
+
|
|
3
16
|
## 1.0.6-next.0
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/index.esm.js
CHANGED
|
@@ -6,7 +6,7 @@ import { SessionState, FeatureFlagState, getComponentData, attachComponentData,
|
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { ConfigReader } from '@backstage/config';
|
|
8
8
|
export { ConfigReader } from '@backstage/config';
|
|
9
|
-
import { matchRoutes, generatePath, useLocation,
|
|
9
|
+
import { matchRoutes, generatePath, useLocation, createRoutesFromChildren, Route, Routes, useRoutes } from 'react-router-dom';
|
|
10
10
|
import useAsync from 'react-use/lib/useAsync';
|
|
11
11
|
import useObservable from 'react-use/lib/useObservable';
|
|
12
12
|
|
|
@@ -1745,10 +1745,142 @@ attachComponentData(FeatureFlagged, "core.featureFlagged", true);
|
|
|
1745
1745
|
|
|
1746
1746
|
const MATCH_ALL_ROUTE = {
|
|
1747
1747
|
caseSensitive: false,
|
|
1748
|
-
path: "
|
|
1748
|
+
path: "*",
|
|
1749
1749
|
element: "match-all",
|
|
1750
1750
|
routeRefs: /* @__PURE__ */ new Set()
|
|
1751
1751
|
};
|
|
1752
|
+
function stringifyNode(node) {
|
|
1753
|
+
var _a, _b;
|
|
1754
|
+
const anyNode = node;
|
|
1755
|
+
if (anyNode == null ? void 0 : anyNode.type) {
|
|
1756
|
+
return (_b = (_a = anyNode.type.displayName) != null ? _a : anyNode.type.name) != null ? _b : String(anyNode.type);
|
|
1757
|
+
}
|
|
1758
|
+
return String(anyNode);
|
|
1759
|
+
}
|
|
1760
|
+
function collectSubTree(node, entries = new Array()) {
|
|
1761
|
+
Children.forEach(node, (element) => {
|
|
1762
|
+
if (!isValidElement(element)) {
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
if (element.props.path) {
|
|
1766
|
+
throw new Error(
|
|
1767
|
+
`Elements within the element prop tree may not have paths, found "${element.props.path}"`
|
|
1768
|
+
);
|
|
1769
|
+
}
|
|
1770
|
+
const routeRef = getComponentData(element, "core.mountPoint");
|
|
1771
|
+
if (routeRef) {
|
|
1772
|
+
const plugin = getComponentData(element, "core.plugin");
|
|
1773
|
+
entries.push({ routeRef, plugin });
|
|
1774
|
+
}
|
|
1775
|
+
collectSubTree(element.props.children, entries);
|
|
1776
|
+
});
|
|
1777
|
+
return entries;
|
|
1778
|
+
}
|
|
1779
|
+
const routingV2Collector = createCollector(
|
|
1780
|
+
() => ({
|
|
1781
|
+
paths: /* @__PURE__ */ new Map(),
|
|
1782
|
+
parents: /* @__PURE__ */ new Map(),
|
|
1783
|
+
objects: new Array()
|
|
1784
|
+
}),
|
|
1785
|
+
(acc, node, parent, ctx) => {
|
|
1786
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1787
|
+
const pathProp = (_a = node.props) == null ? void 0 : _a.path;
|
|
1788
|
+
const mountPoint = getComponentData(node, "core.mountPoint");
|
|
1789
|
+
if (mountPoint && pathProp) {
|
|
1790
|
+
throw new Error(
|
|
1791
|
+
`Path property may not be set directly on a routable extension "${stringifyNode(
|
|
1792
|
+
node
|
|
1793
|
+
)}"`
|
|
1794
|
+
);
|
|
1795
|
+
}
|
|
1796
|
+
if (ctx == null ? void 0 : ctx.isElementAncestor) {
|
|
1797
|
+
return ctx;
|
|
1798
|
+
}
|
|
1799
|
+
if ((parent == null ? void 0 : parent.props.element) === node) {
|
|
1800
|
+
return { ...ctx, isElementAncestor: true };
|
|
1801
|
+
}
|
|
1802
|
+
const parentChildren = (_c = (_b = ctx == null ? void 0 : ctx.obj) == null ? void 0 : _b.children) != null ? _c : acc.objects;
|
|
1803
|
+
if (pathProp !== void 0) {
|
|
1804
|
+
if (typeof pathProp !== "string") {
|
|
1805
|
+
throw new Error(
|
|
1806
|
+
`Element path must be a string at "${stringifyNode(node)}"`
|
|
1807
|
+
);
|
|
1808
|
+
}
|
|
1809
|
+
const path = pathProp.startsWith("/") ? pathProp.slice(1) : pathProp;
|
|
1810
|
+
const elementProp = node.props.element;
|
|
1811
|
+
if (getComponentData(node, "core.gatherMountPoints")) {
|
|
1812
|
+
if (elementProp) {
|
|
1813
|
+
throw new Error(
|
|
1814
|
+
`Mount point gatherers may not have an element prop "${stringifyNode(
|
|
1815
|
+
node
|
|
1816
|
+
)}"`
|
|
1817
|
+
);
|
|
1818
|
+
}
|
|
1819
|
+
const newObj = {
|
|
1820
|
+
path,
|
|
1821
|
+
element: "gathered",
|
|
1822
|
+
routeRefs: /* @__PURE__ */ new Set(),
|
|
1823
|
+
caseSensitive: Boolean((_d = node.props) == null ? void 0 : _d.caseSensitive),
|
|
1824
|
+
children: [MATCH_ALL_ROUTE],
|
|
1825
|
+
plugin: void 0
|
|
1826
|
+
};
|
|
1827
|
+
parentChildren.push(newObj);
|
|
1828
|
+
return {
|
|
1829
|
+
obj: newObj,
|
|
1830
|
+
gatherPath: path,
|
|
1831
|
+
routeRef: ctx == null ? void 0 : ctx.routeRef,
|
|
1832
|
+
gatherRouteRef: ctx == null ? void 0 : ctx.routeRef
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
if (elementProp) {
|
|
1836
|
+
const [extension, ...others] = collectSubTree(elementProp);
|
|
1837
|
+
if (others.length > 0) {
|
|
1838
|
+
throw new Error(
|
|
1839
|
+
`Route element with path "${pathProp}" may not contain multiple routable extensions`
|
|
1840
|
+
);
|
|
1841
|
+
}
|
|
1842
|
+
if (!extension) {
|
|
1843
|
+
return ctx;
|
|
1844
|
+
}
|
|
1845
|
+
const { routeRef, plugin } = extension;
|
|
1846
|
+
const newObj = {
|
|
1847
|
+
path,
|
|
1848
|
+
element: "mounted",
|
|
1849
|
+
routeRefs: /* @__PURE__ */ new Set([routeRef]),
|
|
1850
|
+
caseSensitive: Boolean((_e = node.props) == null ? void 0 : _e.caseSensitive),
|
|
1851
|
+
children: [MATCH_ALL_ROUTE],
|
|
1852
|
+
plugin
|
|
1853
|
+
};
|
|
1854
|
+
parentChildren.push(newObj);
|
|
1855
|
+
acc.paths.set(routeRef, path);
|
|
1856
|
+
acc.parents.set(routeRef, ctx == null ? void 0 : ctx.routeRef);
|
|
1857
|
+
return {
|
|
1858
|
+
obj: newObj,
|
|
1859
|
+
routeRef: routeRef != null ? routeRef : ctx == null ? void 0 : ctx.routeRef,
|
|
1860
|
+
gatherPath: path,
|
|
1861
|
+
gatherRouteRef: ctx == null ? void 0 : ctx.gatherRouteRef
|
|
1862
|
+
};
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
if (mountPoint) {
|
|
1866
|
+
if (!(ctx == null ? void 0 : ctx.gatherPath)) {
|
|
1867
|
+
throw new Error(
|
|
1868
|
+
`Routable extension "${stringifyNode(
|
|
1869
|
+
node
|
|
1870
|
+
)}" with mount point "${mountPoint}" must be assigned a path`
|
|
1871
|
+
);
|
|
1872
|
+
}
|
|
1873
|
+
(_f = ctx == null ? void 0 : ctx.obj) == null ? void 0 : _f.routeRefs.add(mountPoint);
|
|
1874
|
+
acc.paths.set(mountPoint, ctx.gatherPath);
|
|
1875
|
+
acc.parents.set(mountPoint, ctx == null ? void 0 : ctx.gatherRouteRef);
|
|
1876
|
+
return {
|
|
1877
|
+
...ctx,
|
|
1878
|
+
routeRef: mountPoint
|
|
1879
|
+
};
|
|
1880
|
+
}
|
|
1881
|
+
return ctx;
|
|
1882
|
+
}
|
|
1883
|
+
);
|
|
1752
1884
|
const routingV1Collector = createCollector(
|
|
1753
1885
|
() => ({
|
|
1754
1886
|
paths: /* @__PURE__ */ new Map(),
|
|
@@ -1880,6 +2012,7 @@ function joinPaths(...paths) {
|
|
|
1880
2012
|
}
|
|
1881
2013
|
return normalized;
|
|
1882
2014
|
}
|
|
2015
|
+
|
|
1883
2016
|
function resolveTargetRef(anyRouteRef, routePaths, routeBindings) {
|
|
1884
2017
|
let targetRef;
|
|
1885
2018
|
let subRoutePath = "";
|
|
@@ -1914,7 +2047,7 @@ function resolveTargetRef(anyRouteRef, routePaths, routeBindings) {
|
|
|
1914
2047
|
return [void 0, ""];
|
|
1915
2048
|
}
|
|
1916
2049
|
const resolvedPath = routePaths.get(targetRef);
|
|
1917
|
-
if (
|
|
2050
|
+
if (resolvedPath === void 0) {
|
|
1918
2051
|
return [void 0, ""];
|
|
1919
2052
|
}
|
|
1920
2053
|
const targetPath = joinPaths(resolvedPath, subRoutePath);
|
|
@@ -1938,21 +2071,19 @@ function resolveBasePath(targetRef, sourceLocation, routePaths, routeParents, ro
|
|
|
1938
2071
|
matchIndex -= 1;
|
|
1939
2072
|
}
|
|
1940
2073
|
const parentPath = matchIndex === -1 ? "" : match[matchIndex].pathname;
|
|
1941
|
-
const
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
);
|
|
1955
|
-
return parentPath + diffPath;
|
|
2074
|
+
const diffPaths = refDiffList.slice(0, -1).map((ref) => {
|
|
2075
|
+
const path = routePaths.get(ref);
|
|
2076
|
+
if (path === void 0) {
|
|
2077
|
+
throw new Error(`No path for ${ref}`);
|
|
2078
|
+
}
|
|
2079
|
+
if (path.includes(":")) {
|
|
2080
|
+
throw new Error(
|
|
2081
|
+
`Cannot route to ${targetRef} with parent ${ref} as it has parameters`
|
|
2082
|
+
);
|
|
2083
|
+
}
|
|
2084
|
+
return path;
|
|
2085
|
+
});
|
|
2086
|
+
return `${joinPaths(parentPath, ...diffPaths)}/`;
|
|
1956
2087
|
}
|
|
1957
2088
|
class RouteResolver {
|
|
1958
2089
|
constructor(routePaths, routeParents, routeObjects, routeBindings, appBasePath) {
|
|
@@ -1990,7 +2121,7 @@ class RouteResolver {
|
|
|
1990
2121
|
this.routeObjects
|
|
1991
2122
|
);
|
|
1992
2123
|
const routeFunc = (...[params]) => {
|
|
1993
|
-
return basePath
|
|
2124
|
+
return joinPaths(basePath, generatePath(targetPath, params));
|
|
1994
2125
|
};
|
|
1995
2126
|
return routeFunc;
|
|
1996
2127
|
}
|
|
@@ -2088,10 +2219,10 @@ function validateRouteParameters(routePaths, routeParents) {
|
|
|
2088
2219
|
let fullPath = "";
|
|
2089
2220
|
while (currentRouteRef) {
|
|
2090
2221
|
const path = routePaths.get(currentRouteRef);
|
|
2091
|
-
if (
|
|
2222
|
+
if (path === void 0) {
|
|
2092
2223
|
throw new Error(`No path for ${currentRouteRef}`);
|
|
2093
2224
|
}
|
|
2094
|
-
fullPath =
|
|
2225
|
+
fullPath = joinPaths(path, fullPath);
|
|
2095
2226
|
currentRouteRef = routeParents.get(currentRouteRef);
|
|
2096
2227
|
}
|
|
2097
2228
|
const params = fullPath.match(/:(\w+)/g);
|
|
@@ -2360,6 +2491,14 @@ function resolveRouteBindings(bindRoutes) {
|
|
|
2360
2491
|
return result;
|
|
2361
2492
|
}
|
|
2362
2493
|
|
|
2494
|
+
function isReactRouterBeta() {
|
|
2495
|
+
const [obj] = createRoutesFromChildren(/* @__PURE__ */ React.createElement(Route, {
|
|
2496
|
+
index: true,
|
|
2497
|
+
element: /* @__PURE__ */ React.createElement("div", null)
|
|
2498
|
+
}));
|
|
2499
|
+
return !obj.index;
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2363
2502
|
const InternalAppContext = createContext({ routeObjects: [] });
|
|
2364
2503
|
function getBasePath(configApi) {
|
|
2365
2504
|
var _a;
|
|
@@ -2452,7 +2591,7 @@ class AppManager {
|
|
|
2452
2591
|
root: children,
|
|
2453
2592
|
discoverers: [childDiscoverer, routeElementDiscoverer],
|
|
2454
2593
|
collectors: {
|
|
2455
|
-
routing: routingV1Collector,
|
|
2594
|
+
routing: isReactRouterBeta() ? routingV1Collector : routingV2Collector,
|
|
2456
2595
|
collectedPlugins: pluginCollector,
|
|
2457
2596
|
featureFlags: featureFlagCollector
|
|
2458
2597
|
}
|
|
@@ -2680,9 +2819,11 @@ function createSpecializedApp(options) {
|
|
|
2680
2819
|
return new AppManager(options);
|
|
2681
2820
|
}
|
|
2682
2821
|
|
|
2822
|
+
let warned = false;
|
|
2683
2823
|
const FlatRoutes = (props) => {
|
|
2684
2824
|
const app = useApp();
|
|
2685
2825
|
const { NotFoundErrorPage } = app.getComponents();
|
|
2826
|
+
const isBeta = useMemo(() => isReactRouterBeta(), []);
|
|
2686
2827
|
const routes = useElementFilter(
|
|
2687
2828
|
props.children,
|
|
2688
2829
|
(elements) => elements.getElements().flatMap((child) => {
|
|
@@ -2692,28 +2833,38 @@ const FlatRoutes = (props) => {
|
|
|
2692
2833
|
return [];
|
|
2693
2834
|
}
|
|
2694
2835
|
path = (_a = path == null ? void 0 : path.replace(/\/\*$/, "")) != null ? _a : "/";
|
|
2836
|
+
let element = isBeta ? child : child.props.element;
|
|
2837
|
+
if (!isBeta && !element) {
|
|
2838
|
+
element = child;
|
|
2839
|
+
if (!warned && process.env.NODE_ENV !== "test") {
|
|
2840
|
+
console.warn(
|
|
2841
|
+
"DEPRECATION WARNING: All elements within <FlatRoutes> must be of type <Route> with an element prop. Existing usages of <Navigate key=[path] to=[to] /> should be replaced with <Route path=[path] element={<Navigate to=[to] />} />."
|
|
2842
|
+
);
|
|
2843
|
+
warned = true;
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2695
2846
|
return [
|
|
2696
2847
|
{
|
|
2697
2848
|
path,
|
|
2698
|
-
element
|
|
2849
|
+
element,
|
|
2699
2850
|
children: child.props.children ? [
|
|
2700
2851
|
{
|
|
2701
|
-
path: path === "/" ? "/" : "
|
|
2852
|
+
path: path === "/" ? "/" : "*",
|
|
2702
2853
|
element: child.props.children
|
|
2703
2854
|
}
|
|
2704
2855
|
] : void 0
|
|
2705
2856
|
}
|
|
2706
2857
|
];
|
|
2707
|
-
}).sort((a, b) => b.path.localeCompare(a.path)).map((obj) => {
|
|
2708
|
-
obj.path = obj.path === "/" ? "/" : `${obj.path}/*`;
|
|
2709
|
-
return obj;
|
|
2710
|
-
})
|
|
2858
|
+
}).sort((a, b) => b.path.localeCompare(a.path)).map((obj) => ({ ...obj, path: obj.path === "/" ? "/" : `${obj.path}/*` }))
|
|
2711
2859
|
);
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2860
|
+
const withNotFound = [
|
|
2861
|
+
...routes,
|
|
2862
|
+
{
|
|
2863
|
+
path: "*",
|
|
2864
|
+
element: /* @__PURE__ */ React.createElement(NotFoundErrorPage, null)
|
|
2865
|
+
}
|
|
2866
|
+
];
|
|
2867
|
+
return useRoutes(withNotFound);
|
|
2717
2868
|
};
|
|
2718
2869
|
|
|
2719
2870
|
export { AlertApiForwarder, ApiFactoryRegistry, ApiProvider, ApiResolver, AppThemeSelector, AtlassianAuth, BitbucketAuth, ErrorAlerter, ErrorApiForwarder, FeatureFlagged, FetchMiddlewares, FlatRoutes, GithubAuth, GitlabAuth, GoogleAuth, LocalStorageFeatureFlags, MicrosoftAuth, NoOpAnalyticsApi, OAuth2, OAuthRequestManager, OktaAuth, OneLoginAuth, SamlAuth, UnhandledErrorForwarder, UrlPatternDiscovery, WebStorage, createFetchApi, createSpecializedApp, defaultConfigLoader };
|