@backstage/core-app-api 1.14.3-next.0 → 1.15.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,22 @@
1
1
  # @backstage/core-app-api
2
2
 
3
+ ## 1.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ddbeace: Added the ability to explicitly disable routes through the `bindRoutes` option by passing `false` as the route target. This also fixes a bug where route bindings in config were incorrectly prioritized above the ones in code in certain situations.
8
+
9
+ ### Patch Changes
10
+
11
+ - ea69e46: The `defaultConfigLoader` now also reads configuration from scripts tags with `type="backstage.io/config"`. The tag is expected to contain a JSON-serialized array of `AppConfig` objects. If any of these script tags are present, the injected runtime configuration in the static assets will no longer be used.
12
+ - b537bd7: Allow custom star icons to be provided via the `star` and `unstarred` icon overrides. See how to override existing icons in the [Backstage documentation](https://backstage.io/docs/getting-started/app-custom-theme/#custom-icons).
13
+ - 836127c: Updated dependency `@testing-library/react` to `^16.0.0`.
14
+ - Updated dependencies
15
+ - @backstage/core-plugin-api@1.9.4
16
+ - @backstage/version-bridge@1.0.9
17
+ - @backstage/config@1.2.0
18
+ - @backstage/types@1.1.1
19
+
3
20
  ## 1.14.3-next.0
4
21
 
5
22
  ### Patch Changes
@@ -22,6 +22,7 @@ function collectRouteIds(plugins) {
22
22
  function resolveRouteBindings(bindRoutes, config, plugins) {
23
23
  const routesById = collectRouteIds(plugins);
24
24
  const result = /* @__PURE__ */ new Map();
25
+ const disabledExternalRefs = /* @__PURE__ */ new Set();
25
26
  if (bindRoutes) {
26
27
  const bind = (externalRoutes, targetRoutes) => {
27
28
  for (const [key, value] of Object.entries(targetRoutes)) {
@@ -31,18 +32,19 @@ function resolveRouteBindings(bindRoutes, config, plugins) {
31
32
  }
32
33
  if (!value && !externalRoute.optional) {
33
34
  throw new Error(
34
- `External route ${key} is required but was undefined`
35
+ `External route ${key} is required but was ${value === false ? "disabled" : "not provided"}`
35
36
  );
36
37
  }
37
38
  if (value) {
38
39
  result.set(externalRoute, value);
40
+ } else if (value === false) {
41
+ disabledExternalRefs.add(externalRoute);
39
42
  }
40
43
  }
41
44
  };
42
45
  bindRoutes({ bind });
43
46
  }
44
47
  const bindings = config.getOptionalConfig("app.routes.bindings")?.get();
45
- const disabledExternalRefs = /* @__PURE__ */ new Set();
46
48
  if (bindings) {
47
49
  for (const [externalRefId, targetRefId] of Object.entries(bindings)) {
48
50
  if (!isValidTargetRefId(targetRefId)) {
@@ -56,10 +58,12 @@ function resolveRouteBindings(bindRoutes, config, plugins) {
56
58
  `Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`
57
59
  );
58
60
  }
61
+ if (result.has(externalRef) || disabledExternalRefs.has(externalRef)) {
62
+ continue;
63
+ }
59
64
  if (targetRefId === false) {
60
65
  disabledExternalRefs.add(externalRef);
61
- result.delete(externalRef);
62
- } else if (!result.has(externalRef)) {
66
+ } else {
63
67
  const targetRef = routesById.routes.get(targetRefId);
64
68
  if (!targetRef) {
65
69
  throw new Error(
@@ -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 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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"}
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 const disabledExternalRefs = new Set<ExternalRouteRef>();\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 ${\n value === false ? 'disabled' : 'not provided'\n }`,\n );\n }\n if (value) {\n result.set(externalRoute, value);\n } else if (value === false) {\n disabledExternalRefs.add(externalRoute);\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 (!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 // Skip if binding was already defined in code\n if (result.has(externalRef) || disabledExternalRefs.has(externalRef)) {\n continue;\n }\n\n if (targetRefId === false) {\n disabledExternalRefs.add(externalRef);\n } else {\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/dist/index.d.ts CHANGED
@@ -804,7 +804,7 @@ type PartialKeys<Map extends {
804
804
  type TargetRouteMap<ExternalRoutes extends {
805
805
  [name: string]: ExternalRouteRef;
806
806
  }> = {
807
- [name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef<infer Params, any> ? RouteRef<Params> | SubRouteRef<Params> : never;
807
+ [name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef<infer Params, any> ? RouteRef<Params> | SubRouteRef<Params> | false : never;
808
808
  };
809
809
  /**
810
810
  * A function that can bind from external routes of a given plugin, to concrete
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.14.3-next.0",
4
+ "version": "1.15.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -40,9 +40,9 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@backstage/config": "^1.2.0",
43
- "@backstage/core-plugin-api": "^1.9.4-next.0",
43
+ "@backstage/core-plugin-api": "^1.9.4",
44
44
  "@backstage/types": "^1.1.1",
45
- "@backstage/version-bridge": "^1.0.9-next.0",
45
+ "@backstage/version-bridge": "^1.0.9",
46
46
  "@types/prop-types": "^15.7.3",
47
47
  "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
48
48
  "history": "^5.0.0",
@@ -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.27.1-next.2",
63
- "@backstage/test-utils": "^1.6.0-next.1",
62
+ "@backstage/cli": "^0.27.1",
63
+ "@backstage/test-utils": "^1.6.0",
64
64
  "@testing-library/dom": "^10.0.0",
65
65
  "@testing-library/jest-dom": "^6.0.0",
66
66
  "@testing-library/react": "^16.0.0",