@backstage/core-app-api 1.12.6 → 1.13.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.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @backstage/core-app-api
|
|
2
2
|
|
|
3
|
+
## 1.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5a5afe1: Allow for the disabling of external routes through config, which was rendered impossible after the introduction of default targets.
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
app:
|
|
11
|
+
routes:
|
|
12
|
+
bindings:
|
|
13
|
+
# This has the effect of removing the button for registering new
|
|
14
|
+
# catalog entities in the scaffolder template list view
|
|
15
|
+
scaffolder.registerComponent: false
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
- @backstage/core-plugin-api@1.9.3
|
|
22
|
+
- @backstage/config@1.2.0
|
|
23
|
+
- @backstage/types@1.1.1
|
|
24
|
+
- @backstage/version-bridge@1.0.8
|
|
25
|
+
|
|
3
26
|
## 1.12.6
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
|
@@ -42,11 +42,12 @@ function resolveRouteBindings(bindRoutes, config, plugins) {
|
|
|
42
42
|
bindRoutes({ bind });
|
|
43
43
|
}
|
|
44
44
|
const bindings = config.getOptionalConfig("app.routes.bindings")?.get();
|
|
45
|
+
const disabledExternalRefs = /* @__PURE__ */ new Set();
|
|
45
46
|
if (bindings) {
|
|
46
47
|
for (const [externalRefId, targetRefId] of Object.entries(bindings)) {
|
|
47
|
-
if (
|
|
48
|
+
if (!isValidTargetRefId(targetRefId)) {
|
|
48
49
|
throw new Error(
|
|
49
|
-
`Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string`
|
|
50
|
+
`Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string or false`
|
|
50
51
|
);
|
|
51
52
|
}
|
|
52
53
|
const externalRef = routesById.externalRoutes.get(externalRefId);
|
|
@@ -55,20 +56,22 @@ function resolveRouteBindings(bindRoutes, config, plugins) {
|
|
|
55
56
|
`Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`
|
|
56
57
|
);
|
|
57
58
|
}
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
if (targetRefId === false) {
|
|
60
|
+
disabledExternalRefs.add(externalRef);
|
|
61
|
+
result.delete(externalRef);
|
|
62
|
+
} else if (!result.has(externalRef)) {
|
|
63
|
+
const targetRef = routesById.routes.get(targetRefId);
|
|
64
|
+
if (!targetRef) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
`Invalid config at app.routes.bindings['${externalRefId}'], '${targetRefId}' is not a valid route`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
result.set(externalRef, targetRef);
|
|
66
70
|
}
|
|
67
|
-
result.set(externalRef, targetRef);
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
for (const externalRef of routesById.externalRoutes.values()) {
|
|
71
|
-
if (!result.has(externalRef)) {
|
|
74
|
+
if (!result.has(externalRef) && !disabledExternalRefs.has(externalRef)) {
|
|
72
75
|
const defaultRefId = "getDefaultTarget" in externalRef ? externalRef.getDefaultTarget() : void 0;
|
|
73
76
|
if (defaultRefId) {
|
|
74
77
|
const defaultRef = routesById.routes.get(defaultRefId);
|
|
@@ -80,6 +83,15 @@ function resolveRouteBindings(bindRoutes, config, plugins) {
|
|
|
80
83
|
}
|
|
81
84
|
return result;
|
|
82
85
|
}
|
|
86
|
+
function isValidTargetRefId(value) {
|
|
87
|
+
if (value === false) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
if (typeof value === "string" && value) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
83
95
|
|
|
84
96
|
export { collectRouteIds, resolveRouteBindings };
|
|
85
97
|
//# sourceMappingURL=resolveRouteBindings.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveRouteBindings.esm.js","sources":["../../src/app/resolveRouteBindings.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RouteRef,\n SubRouteRef,\n ExternalRouteRef,\n BackstagePlugin,\n AnyRoutes,\n AnyExternalRoutes,\n} from '@backstage/core-plugin-api';\nimport { AppOptions, AppRouteBinder } from './types';\nimport { Config } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\n\n/** @internal */\nexport function collectRouteIds(\n plugins: Iterable<\n Pick<\n BackstagePlugin<AnyRoutes, AnyExternalRoutes>,\n 'getId' | 'routes' | 'externalRoutes'\n >\n >,\n) {\n const routesById = new Map<string, RouteRef | SubRouteRef>();\n const externalRoutesById = new Map<string, ExternalRouteRef>();\n\n for (const plugin of plugins) {\n for (const [name, ref] of Object.entries(plugin.routes ?? {})) {\n const refId = `${plugin.getId()}.${name}`;\n if (routesById.has(refId)) {\n throw new Error(`Unexpected duplicate route '${refId}'`);\n }\n\n routesById.set(refId, ref);\n }\n for (const [name, ref] of Object.entries(plugin.externalRoutes ?? {})) {\n const refId = `${plugin.getId()}.${name}`;\n if (externalRoutesById.has(refId)) {\n throw new Error(`Unexpected duplicate external route '${refId}'`);\n }\n\n externalRoutesById.set(refId, ref);\n }\n }\n\n return { routes: routesById, externalRoutes: externalRoutesById };\n}\n\n/** @internal */\nexport function resolveRouteBindings(\n bindRoutes: AppOptions['bindRoutes'],\n config: Config,\n plugins: Iterable<\n Pick<\n BackstagePlugin<AnyRoutes, AnyExternalRoutes>,\n 'getId' | 'routes' | 'externalRoutes'\n >\n >,\n) {\n const routesById = collectRouteIds(plugins);\n const result = new Map<ExternalRouteRef, RouteRef | SubRouteRef>();\n\n // Perform callback bindings first with highest priority\n if (bindRoutes) {\n const bind: AppRouteBinder = (\n externalRoutes,\n targetRoutes: { [name: string]: RouteRef | SubRouteRef },\n ) => {\n for (const [key, value] of Object.entries(targetRoutes)) {\n const externalRoute = externalRoutes[key];\n if (!externalRoute) {\n throw new Error(`Key ${key} is not an existing external route`);\n }\n if (!value && !externalRoute.optional) {\n throw new Error(\n `External route ${key} is required but was undefined`,\n );\n }\n if (value) {\n result.set(externalRoute, value);\n }\n }\n };\n bindRoutes({ bind });\n }\n\n // Then perform config based bindings with lower priority\n const bindings = config\n .getOptionalConfig('app.routes.bindings')\n ?.get<JsonObject>();\n if (bindings) {\n for (const [externalRefId, targetRefId] of Object.entries(bindings)) {\n if (
|
|
1
|
+
{"version":3,"file":"resolveRouteBindings.esm.js","sources":["../../src/app/resolveRouteBindings.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RouteRef,\n SubRouteRef,\n ExternalRouteRef,\n BackstagePlugin,\n AnyRoutes,\n AnyExternalRoutes,\n} from '@backstage/core-plugin-api';\nimport { AppOptions, AppRouteBinder } from './types';\nimport { Config } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\n\n/** @internal */\nexport function collectRouteIds(\n plugins: Iterable<\n Pick<\n BackstagePlugin<AnyRoutes, AnyExternalRoutes>,\n 'getId' | 'routes' | 'externalRoutes'\n >\n >,\n) {\n const routesById = new Map<string, RouteRef | SubRouteRef>();\n const externalRoutesById = new Map<string, ExternalRouteRef>();\n\n for (const plugin of plugins) {\n for (const [name, ref] of Object.entries(plugin.routes ?? {})) {\n const refId = `${plugin.getId()}.${name}`;\n if (routesById.has(refId)) {\n throw new Error(`Unexpected duplicate route '${refId}'`);\n }\n\n routesById.set(refId, ref);\n }\n for (const [name, ref] of Object.entries(plugin.externalRoutes ?? {})) {\n const refId = `${plugin.getId()}.${name}`;\n if (externalRoutesById.has(refId)) {\n throw new Error(`Unexpected duplicate external route '${refId}'`);\n }\n\n externalRoutesById.set(refId, ref);\n }\n }\n\n return { routes: routesById, externalRoutes: externalRoutesById };\n}\n\n/** @internal */\nexport function resolveRouteBindings(\n bindRoutes: AppOptions['bindRoutes'],\n config: Config,\n plugins: Iterable<\n Pick<\n BackstagePlugin<AnyRoutes, AnyExternalRoutes>,\n 'getId' | 'routes' | 'externalRoutes'\n >\n >,\n) {\n const routesById = collectRouteIds(plugins);\n const result = new Map<ExternalRouteRef, RouteRef | SubRouteRef>();\n\n // Perform callback bindings first with highest priority\n if (bindRoutes) {\n const bind: AppRouteBinder = (\n externalRoutes,\n targetRoutes: { [name: string]: RouteRef | SubRouteRef },\n ) => {\n for (const [key, value] of Object.entries(targetRoutes)) {\n const externalRoute = externalRoutes[key];\n if (!externalRoute) {\n throw new Error(`Key ${key} is not an existing external route`);\n }\n if (!value && !externalRoute.optional) {\n throw new Error(\n `External route ${key} is required but was undefined`,\n );\n }\n if (value) {\n result.set(externalRoute, value);\n }\n }\n };\n bindRoutes({ bind });\n }\n\n // Then perform config based bindings with lower priority\n const bindings = config\n .getOptionalConfig('app.routes.bindings')\n ?.get<JsonObject>();\n const disabledExternalRefs = new Set<ExternalRouteRef>();\n if (bindings) {\n for (const [externalRefId, targetRefId] of Object.entries(bindings)) {\n if (!isValidTargetRefId(targetRefId)) {\n throw new Error(\n `Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string or false`,\n );\n }\n\n const externalRef = routesById.externalRoutes.get(externalRefId);\n if (!externalRef) {\n throw new Error(\n `Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`,\n );\n }\n\n if (targetRefId === false) {\n disabledExternalRefs.add(externalRef);\n\n result.delete(externalRef);\n } else if (!result.has(externalRef)) {\n const targetRef = routesById.routes.get(targetRefId);\n if (!targetRef) {\n throw new Error(\n `Invalid config at app.routes.bindings['${externalRefId}'], '${targetRefId}' is not a valid route`,\n );\n }\n\n result.set(externalRef, targetRef);\n }\n }\n }\n\n // Finally fall back to attempting to map defaults, at lowest priority\n for (const externalRef of routesById.externalRoutes.values()) {\n if (!result.has(externalRef) && !disabledExternalRefs.has(externalRef)) {\n const defaultRefId =\n 'getDefaultTarget' in externalRef\n ? (externalRef.getDefaultTarget as () => string | undefined)()\n : undefined;\n if (defaultRefId) {\n const defaultRef = routesById.routes.get(defaultRefId);\n if (defaultRef) {\n result.set(externalRef, defaultRef);\n }\n }\n }\n }\n\n return result;\n}\n\nfunction isValidTargetRefId(value: unknown): value is string | false {\n if (value === false) {\n return true;\n }\n\n if (typeof value === 'string' && value) {\n return true;\n }\n\n return false;\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/core-app-api",
|
|
3
3
|
"description": "Core app API used by Backstage apps",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.13.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@backstage/cli": "^0.26.
|
|
63
|
-
"@backstage/test-utils": "^1.5.
|
|
62
|
+
"@backstage/cli": "^0.26.10",
|
|
63
|
+
"@backstage/test-utils": "^1.5.7",
|
|
64
64
|
"@testing-library/dom": "^10.0.0",
|
|
65
65
|
"@testing-library/jest-dom": "^6.0.0",
|
|
66
66
|
"@testing-library/react": "^15.0.0",
|