@backstage/frontend-app-api 0.3.0-next.0 → 0.3.0-next.2
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 +33 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +58 -53
- package/dist/index.esm.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @backstage/frontend-app-api
|
|
2
2
|
|
|
3
|
+
## 0.3.0-next.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#20999](https://github.com/backstage/backstage/pull/20999) [`fdc348d5d3`](https://github.com/backstage/backstage/commit/fdc348d5d30a98b52d8a756daba29d616418da93) Thanks [@Rugvip](https://github.com/Rugvip)! - The options parameter of `createApp` is now optional.
|
|
8
|
+
|
|
9
|
+
- [#20888](https://github.com/backstage/backstage/pull/20888) [`733bd95746`](https://github.com/backstage/backstage/commit/733bd95746b99ad8cdb4a7b87e8dc3e16d3b764a) Thanks [@Rugvip](https://github.com/Rugvip)! - Implement new `AppTreeApi`
|
|
10
|
+
|
|
11
|
+
- [#20999](https://github.com/backstage/backstage/pull/20999) [`fa28d4e6df`](https://github.com/backstage/backstage/commit/fa28d4e6dfcbee2bc8695b7b24289a401df96acd) Thanks [@Rugvip](https://github.com/Rugvip)! - No longer throw error on invalid input if the child is disabled.
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
- @backstage/core-components@0.13.8-next.2
|
|
15
|
+
- @backstage/frontend-plugin-api@0.3.0-next.2
|
|
16
|
+
- @backstage/plugin-graphiql@0.3.0-next.2
|
|
17
|
+
|
|
18
|
+
## 0.3.0-next.1
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- fe6d09953d: Fix for app node output IDs not being serialized correctly.
|
|
23
|
+
- 77f009b35d: Internal updates to match changes in the experimental `@backstage/frontend-plugin-api`.
|
|
24
|
+
- 4d6fa921db: Internal refactor to rename the app graph to app tree
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
- @backstage/frontend-plugin-api@0.3.0-next.1
|
|
27
|
+
- @backstage/plugin-graphiql@0.3.0-next.1
|
|
28
|
+
- @backstage/core-components@0.13.8-next.1
|
|
29
|
+
- @backstage/config@1.1.1
|
|
30
|
+
- @backstage/core-app-api@1.11.1-next.0
|
|
31
|
+
- @backstage/core-plugin-api@1.8.0-next.0
|
|
32
|
+
- @backstage/theme@0.4.4-next.0
|
|
33
|
+
- @backstage/types@1.1.1
|
|
34
|
+
- @backstage/version-bridge@1.0.7-next.0
|
|
35
|
+
|
|
3
36
|
## 0.3.0-next.0
|
|
4
37
|
|
|
5
38
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -58,7 +58,7 @@ declare function createExtensionTree(options: {
|
|
|
58
58
|
config: Config;
|
|
59
59
|
}): ExtensionTree;
|
|
60
60
|
/** @public */
|
|
61
|
-
declare function createApp(options
|
|
61
|
+
declare function createApp(options?: {
|
|
62
62
|
features?: (BackstagePlugin | ExtensionOverrides)[];
|
|
63
63
|
configLoader?: () => Promise<ConfigApi>;
|
|
64
64
|
bindRoutes?(context: {
|
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useMemo, useState, useEffect } from 'react';
|
|
2
2
|
import { ConfigReader } from '@backstage/config';
|
|
3
|
-
import { createExtension, createExtensionInput, coreExtensionData, useRouteRef, createThemeExtension } from '@backstage/frontend-plugin-api';
|
|
3
|
+
import { createExtension, createExtensionInput, coreExtensionData, useRouteRef, createThemeExtension, appTreeApiRef } from '@backstage/frontend-plugin-api';
|
|
4
4
|
import { useRoutes, BrowserRouter, useInRouterContext, MemoryRouter, matchRoutes, generatePath, Route } from 'react-router-dom';
|
|
5
5
|
import { SidebarPage, sidebarConfig, Sidebar, SidebarDivider, useSidebarOpenState, Link, SidebarItem, Progress, ErrorPage, ErrorPanel } from '@backstage/core-components';
|
|
6
6
|
import { makeStyles } from '@material-ui/core';
|
|
@@ -60,10 +60,10 @@ const Core = createExtension({
|
|
|
60
60
|
output: {
|
|
61
61
|
root: coreExtensionData.reactElement
|
|
62
62
|
},
|
|
63
|
-
factory({
|
|
64
|
-
|
|
63
|
+
factory({ inputs }) {
|
|
64
|
+
return {
|
|
65
65
|
root: inputs.root.element
|
|
66
|
-
}
|
|
66
|
+
};
|
|
67
67
|
}
|
|
68
68
|
});
|
|
69
69
|
|
|
@@ -80,7 +80,7 @@ const CoreRoutes = createExtension({
|
|
|
80
80
|
output: {
|
|
81
81
|
element: coreExtensionData.reactElement
|
|
82
82
|
},
|
|
83
|
-
factory({
|
|
83
|
+
factory({ inputs }) {
|
|
84
84
|
const Routes = () => {
|
|
85
85
|
const element = useRoutes(
|
|
86
86
|
inputs.routes.map((route) => ({
|
|
@@ -90,9 +90,9 @@ const CoreRoutes = createExtension({
|
|
|
90
90
|
);
|
|
91
91
|
return element;
|
|
92
92
|
};
|
|
93
|
-
|
|
93
|
+
return {
|
|
94
94
|
element: /* @__PURE__ */ React.createElement(Routes, null)
|
|
95
|
-
}
|
|
95
|
+
};
|
|
96
96
|
}
|
|
97
97
|
});
|
|
98
98
|
|
|
@@ -116,10 +116,10 @@ const CoreLayout = createExtension({
|
|
|
116
116
|
output: {
|
|
117
117
|
element: coreExtensionData.reactElement
|
|
118
118
|
},
|
|
119
|
-
factory({
|
|
120
|
-
|
|
119
|
+
factory({ inputs }) {
|
|
120
|
+
return {
|
|
121
121
|
element: /* @__PURE__ */ React.createElement(SidebarPage, null, inputs.nav.element, inputs.content.element)
|
|
122
|
-
}
|
|
122
|
+
};
|
|
123
123
|
}
|
|
124
124
|
});
|
|
125
125
|
|
|
@@ -214,10 +214,10 @@ const CoreNav = createExtension({
|
|
|
214
214
|
output: {
|
|
215
215
|
element: coreExtensionData.reactElement
|
|
216
216
|
},
|
|
217
|
-
factory({
|
|
218
|
-
|
|
217
|
+
factory({ inputs }) {
|
|
218
|
+
return {
|
|
219
219
|
element: /* @__PURE__ */ React.createElement(Sidebar, null, /* @__PURE__ */ React.createElement(SidebarLogo, null), /* @__PURE__ */ React.createElement(SidebarDivider, null), inputs.items.map((item, index) => /* @__PURE__ */ React.createElement(SidebarNavItem, { ...item.target, key: index })))
|
|
220
|
-
}
|
|
220
|
+
};
|
|
221
221
|
}
|
|
222
222
|
});
|
|
223
223
|
|
|
@@ -1827,7 +1827,7 @@ class SerializableAppNode {
|
|
|
1827
1827
|
}
|
|
1828
1828
|
toString() {
|
|
1829
1829
|
const dataRefs = this.instance && [...this.instance.getDataRefs()];
|
|
1830
|
-
const out = dataRefs && dataRefs.length > 0 ? ` out=[${[...dataRefs.
|
|
1830
|
+
const out = dataRefs && dataRefs.length > 0 ? ` out=[${[...dataRefs].map((r) => r.id).join(", ")}]` : "";
|
|
1831
1831
|
if (this.edges.attachments.size === 0) {
|
|
1832
1832
|
return `<${this.spec.id}${out} />`;
|
|
1833
1833
|
}
|
|
@@ -1840,7 +1840,7 @@ class SerializableAppNode {
|
|
|
1840
1840
|
].join("\n");
|
|
1841
1841
|
}
|
|
1842
1842
|
}
|
|
1843
|
-
function
|
|
1843
|
+
function resolveAppTree(rootNodeId, specs) {
|
|
1844
1844
|
const nodes = /* @__PURE__ */ new Map();
|
|
1845
1845
|
let rootNode = void 0;
|
|
1846
1846
|
const orphansByParent = /* @__PURE__ */ new Map();
|
|
@@ -1874,7 +1874,7 @@ function resolveAppGraph(rootNodeId, specs) {
|
|
|
1874
1874
|
}
|
|
1875
1875
|
}
|
|
1876
1876
|
if (!rootNode) {
|
|
1877
|
-
throw new Error(`No root node with id '${rootNodeId}' found in app
|
|
1877
|
+
throw new Error(`No root node with id '${rootNodeId}' found in app tree`);
|
|
1878
1878
|
}
|
|
1879
1879
|
return {
|
|
1880
1880
|
root: rootNode,
|
|
@@ -2035,7 +2035,7 @@ function resolveAppNodeSpecs(options) {
|
|
|
2035
2035
|
throw new Error(`Extension ${extensionId} does not exist`);
|
|
2036
2036
|
}
|
|
2037
2037
|
}
|
|
2038
|
-
return configuredExtensions.
|
|
2038
|
+
return configuredExtensions.map((param) => ({
|
|
2039
2039
|
id: param.extension.id,
|
|
2040
2040
|
attachTo: param.params.attachTo,
|
|
2041
2041
|
extension: param.extension,
|
|
@@ -2106,26 +2106,24 @@ function createAppNodeInstance(options) {
|
|
|
2106
2106
|
);
|
|
2107
2107
|
}
|
|
2108
2108
|
try {
|
|
2109
|
-
extension.factory({
|
|
2109
|
+
const namedOutputs = extension.factory({
|
|
2110
2110
|
source,
|
|
2111
2111
|
config: parsedConfig,
|
|
2112
|
-
bind: (namedOutputs) => {
|
|
2113
|
-
for (const [name, output] of Object.entries(namedOutputs)) {
|
|
2114
|
-
const ref = extension.output[name];
|
|
2115
|
-
if (!ref) {
|
|
2116
|
-
throw new Error(`unknown output provided via '${name}'`);
|
|
2117
|
-
}
|
|
2118
|
-
if (extensionData.has(ref.id)) {
|
|
2119
|
-
throw new Error(
|
|
2120
|
-
`duplicate extension data '${ref.id}' received via output '${name}'`
|
|
2121
|
-
);
|
|
2122
|
-
}
|
|
2123
|
-
extensionData.set(ref.id, output);
|
|
2124
|
-
extensionDataRefs.add(ref);
|
|
2125
|
-
}
|
|
2126
|
-
},
|
|
2127
2112
|
inputs: resolveInputs(extension.inputs, attachments)
|
|
2128
2113
|
});
|
|
2114
|
+
for (const [name, output] of Object.entries(namedOutputs)) {
|
|
2115
|
+
const ref = extension.output[name];
|
|
2116
|
+
if (!ref) {
|
|
2117
|
+
throw new Error(`unknown output provided via '${name}'`);
|
|
2118
|
+
}
|
|
2119
|
+
if (extensionData.has(ref.id)) {
|
|
2120
|
+
throw new Error(
|
|
2121
|
+
`duplicate extension data '${ref.id}' received via output '${name}'`
|
|
2122
|
+
);
|
|
2123
|
+
}
|
|
2124
|
+
extensionData.set(ref.id, output);
|
|
2125
|
+
extensionDataRefs.add(ref);
|
|
2126
|
+
}
|
|
2129
2127
|
} catch (e) {
|
|
2130
2128
|
throw new Error(
|
|
2131
2129
|
`Failed to instantiate extension '${id}'${e.name === "Error" ? `, ${e.message}` : `; caused by ${e}`}`
|
|
@@ -2157,7 +2155,9 @@ function instantiateAppNodeTree(rootNode) {
|
|
|
2157
2155
|
}
|
|
2158
2156
|
return [{ id: child.spec.id, instance: childInstance }];
|
|
2159
2157
|
});
|
|
2160
|
-
|
|
2158
|
+
if (instantiatedChildren.length > 0) {
|
|
2159
|
+
instantiatedAttachments.set(input, instantiatedChildren);
|
|
2160
|
+
}
|
|
2161
2161
|
}
|
|
2162
2162
|
node.instance = createAppNodeInstance({
|
|
2163
2163
|
spec: node.spec,
|
|
@@ -2168,8 +2168,8 @@ function instantiateAppNodeTree(rootNode) {
|
|
|
2168
2168
|
createInstance(rootNode);
|
|
2169
2169
|
}
|
|
2170
2170
|
|
|
2171
|
-
function
|
|
2172
|
-
const
|
|
2171
|
+
function createAppTree(options) {
|
|
2172
|
+
const tree = resolveAppTree(
|
|
2173
2173
|
"core",
|
|
2174
2174
|
resolveAppNodeSpecs({
|
|
2175
2175
|
features: options.features,
|
|
@@ -2178,8 +2178,8 @@ function createAppGraph(options) {
|
|
|
2178
2178
|
forbidden: /* @__PURE__ */ new Set(["core"])
|
|
2179
2179
|
})
|
|
2180
2180
|
);
|
|
2181
|
-
instantiateAppNodeTree(
|
|
2182
|
-
return
|
|
2181
|
+
instantiateAppNodeTree(tree.root);
|
|
2182
|
+
return tree;
|
|
2183
2183
|
}
|
|
2184
2184
|
|
|
2185
2185
|
const builtinExtensions = [
|
|
@@ -2192,7 +2192,7 @@ const builtinExtensions = [
|
|
|
2192
2192
|
];
|
|
2193
2193
|
function createExtensionTree(options) {
|
|
2194
2194
|
const features = getAvailableFeatures(options.config);
|
|
2195
|
-
const
|
|
2195
|
+
const tree = createAppTree({
|
|
2196
2196
|
features,
|
|
2197
2197
|
builtinExtensions,
|
|
2198
2198
|
config: options.config
|
|
@@ -2208,11 +2208,11 @@ function createExtensionTree(options) {
|
|
|
2208
2208
|
}
|
|
2209
2209
|
return {
|
|
2210
2210
|
getExtension(id) {
|
|
2211
|
-
return convertNode(
|
|
2211
|
+
return convertNode(tree.nodes.get(id));
|
|
2212
2212
|
},
|
|
2213
2213
|
getExtensionAttachments(id, inputName) {
|
|
2214
2214
|
var _a, _b, _c;
|
|
2215
|
-
return (_c = (_b = (_a =
|
|
2215
|
+
return (_c = (_b = (_a = tree.nodes.get(id)) == null ? void 0 : _a.edges.attachments.get(inputName)) == null ? void 0 : _b.map(convertNode).filter((node) => Boolean(node))) != null ? _c : [];
|
|
2216
2216
|
},
|
|
2217
2217
|
getRootRoutes() {
|
|
2218
2218
|
return this.getExtensionAttachments("core.routes", "routes").map((node) => {
|
|
@@ -2273,13 +2273,13 @@ function createApp(options) {
|
|
|
2273
2273
|
overrideBaseUrlConfigs(defaultConfigLoaderSync())
|
|
2274
2274
|
);
|
|
2275
2275
|
const discoveredFeatures = getAvailableFeatures(config);
|
|
2276
|
-
const loadedFeatures = (_d = await ((_c = options.featureLoader) == null ? void 0 : _c.call(options, { config }))) != null ? _d : [];
|
|
2276
|
+
const loadedFeatures = (_d = await ((_c = options == null ? void 0 : options.featureLoader) == null ? void 0 : _c.call(options, { config }))) != null ? _d : [];
|
|
2277
2277
|
const allFeatures = deduplicateFeatures([
|
|
2278
2278
|
...discoveredFeatures,
|
|
2279
2279
|
...loadedFeatures,
|
|
2280
|
-
...(_e = options.features) != null ? _e : []
|
|
2280
|
+
...(_e = options == null ? void 0 : options.features) != null ? _e : []
|
|
2281
2281
|
]);
|
|
2282
|
-
const
|
|
2282
|
+
const tree = createAppTree({
|
|
2283
2283
|
features: allFeatures,
|
|
2284
2284
|
builtinExtensions,
|
|
2285
2285
|
config
|
|
@@ -2290,19 +2290,17 @@ function createApp(options) {
|
|
|
2290
2290
|
)
|
|
2291
2291
|
);
|
|
2292
2292
|
const routeIds = collectRouteIds(allFeatures);
|
|
2293
|
-
const App = () => /* @__PURE__ */ React.createElement(ApiProvider, { apis: createApiHolder(
|
|
2293
|
+
const App = () => /* @__PURE__ */ React.createElement(ApiProvider, { apis: createApiHolder(tree, config) }, /* @__PURE__ */ React.createElement(AppContextProvider, { appContext }, /* @__PURE__ */ React.createElement(AppThemeProvider, null, /* @__PURE__ */ React.createElement(
|
|
2294
2294
|
RoutingProvider,
|
|
2295
2295
|
{
|
|
2296
|
-
...extractRouteInfoFromAppNode(
|
|
2296
|
+
...extractRouteInfoFromAppNode(tree.root),
|
|
2297
2297
|
routeBindings: resolveRouteBindings(
|
|
2298
|
-
options.bindRoutes,
|
|
2298
|
+
options == null ? void 0 : options.bindRoutes,
|
|
2299
2299
|
config,
|
|
2300
2300
|
routeIds
|
|
2301
2301
|
)
|
|
2302
2302
|
},
|
|
2303
|
-
/* @__PURE__ */ React.createElement(BrowserRouter, null,
|
|
2304
|
-
coreExtensionData.reactElement
|
|
2305
|
-
))
|
|
2303
|
+
/* @__PURE__ */ React.createElement(BrowserRouter, null, tree.root.instance.getData(coreExtensionData.reactElement))
|
|
2306
2304
|
))));
|
|
2307
2305
|
return { default: App };
|
|
2308
2306
|
}
|
|
@@ -2359,14 +2357,14 @@ function createLegacyAppContext(plugins) {
|
|
|
2359
2357
|
}
|
|
2360
2358
|
};
|
|
2361
2359
|
}
|
|
2362
|
-
function createApiHolder(
|
|
2360
|
+
function createApiHolder(tree, configApi) {
|
|
2363
2361
|
var _a, _b, _c, _d;
|
|
2364
2362
|
const factoryRegistry = new ApiFactoryRegistry();
|
|
2365
|
-
const pluginApis = (_b = (_a =
|
|
2363
|
+
const pluginApis = (_b = (_a = tree.root.edges.attachments.get("apis")) == null ? void 0 : _a.map((e) => {
|
|
2366
2364
|
var _a2;
|
|
2367
2365
|
return (_a2 = e.instance) == null ? void 0 : _a2.getData(coreExtensionData.apiFactory);
|
|
2368
2366
|
}).filter((x) => !!x)) != null ? _b : [];
|
|
2369
|
-
const themeExtensions = (_d = (_c =
|
|
2367
|
+
const themeExtensions = (_d = (_c = tree.root.edges.attachments.get("themes")) == null ? void 0 : _c.map((e) => {
|
|
2370
2368
|
var _a2;
|
|
2371
2369
|
return (_a2 = e.instance) == null ? void 0 : _a2.getData(coreExtensionData.theme);
|
|
2372
2370
|
}).filter((x) => !!x)) != null ? _d : [];
|
|
@@ -2409,6 +2407,13 @@ function createApiHolder(core, configApi) {
|
|
|
2409
2407
|
return appIdentityProxy;
|
|
2410
2408
|
}
|
|
2411
2409
|
});
|
|
2410
|
+
factoryRegistry.register("static", {
|
|
2411
|
+
api: appTreeApiRef,
|
|
2412
|
+
deps: {},
|
|
2413
|
+
factory: () => ({
|
|
2414
|
+
getTree: () => ({ tree })
|
|
2415
|
+
})
|
|
2416
|
+
});
|
|
2412
2417
|
factoryRegistry.register("static", {
|
|
2413
2418
|
api: appThemeApiRef,
|
|
2414
2419
|
deps: {},
|