@backstage/frontend-app-api 0.16.7-next.0 → 0.16.7-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
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @backstage/frontend-app-api
|
|
2
2
|
|
|
3
|
+
## 0.16.7-next.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6497d0f: Respect explicit API reference plugin ownership when resolving conflicting API factories.
|
|
8
|
+
- a8b5ba6: Updated dependencies.
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
- @backstage/frontend-plugin-api@0.18.0-next.0
|
|
11
|
+
- @backstage/core-plugin-api@1.12.9-next.0
|
|
12
|
+
- @backstage/frontend-defaults@0.5.5-next.1
|
|
13
|
+
- @backstage/core-app-api@1.20.4-next.1
|
|
14
|
+
|
|
3
15
|
## 0.16.7-next.0
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpaqueApiRef.esm.js","sources":["../../../../../frontend-internal/src/apis/OpaqueApiRef.ts"],"sourcesContent":["/*\n * Copyright 2024 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 type { ApiRef } from '@backstage/frontend-plugin-api';\nimport { OpaqueType } from '@internal/opaque';\n\nexport const OpaqueApiRef = OpaqueType.create<{\n public: ApiRef<unknown> & {\n readonly $$type: '@backstage/ApiRef';\n };\n versions: {\n readonly version: 'v1';\n readonly pluginId?: string;\n };\n}>({\n type: '@backstage/ApiRef',\n versions: ['v1'],\n});\n"],"names":[],"mappings":";;AAmBO,MAAM,YAAA,GAAe,WAAW,MAAA,CAQpC;AAAA,EACD,IAAA,EAAM,mBAAA;AAAA,EACN,QAAA,EAAU,CAAC,IAAI;AACjB,CAAC;;;;"}
|
|
@@ -5,6 +5,7 @@ import { OpaqueFrontendPlugin } from '../frontend-internal/src/wiring/InternalFr
|
|
|
5
5
|
import '../frontend-internal/src/wiring/InternalExtensionDefinition.esm.js';
|
|
6
6
|
import '../frontend-internal/src/wiring/InternalExtensionInput.esm.js';
|
|
7
7
|
import '../frontend-internal/src/wiring/InternalSwappableComponentRef.esm.js';
|
|
8
|
+
import { OpaqueApiRef } from '../frontend-internal/src/apis/OpaqueApiRef.esm.js';
|
|
8
9
|
|
|
9
10
|
function registerFeatureFlagDeclarationsInHolder(apis, features, collector) {
|
|
10
11
|
const featureFlagApi = apis.get(featureFlagsApiRef);
|
|
@@ -142,7 +143,7 @@ function collectApiFactoryEntries(options) {
|
|
|
142
143
|
);
|
|
143
144
|
if (apiFactory) {
|
|
144
145
|
const apiRefId = apiFactory.api.id;
|
|
145
|
-
const ownerId = getApiOwnerId(
|
|
146
|
+
const ownerId = getApiOwnerId(apiFactory.api);
|
|
146
147
|
const pluginId = apiNode.spec.plugin.pluginId ?? "app";
|
|
147
148
|
const existingFactory = factoriesById.get(apiRefId);
|
|
148
149
|
if (existingFactory && existingFactory.pluginId !== pluginId) {
|
|
@@ -185,7 +186,14 @@ function collectApiFactoryEntries(options) {
|
|
|
185
186
|
}
|
|
186
187
|
return factoriesById;
|
|
187
188
|
}
|
|
188
|
-
function getApiOwnerId(
|
|
189
|
+
function getApiOwnerId(apiRef) {
|
|
190
|
+
if (OpaqueApiRef.isType(apiRef)) {
|
|
191
|
+
const { pluginId } = OpaqueApiRef.toInternal(apiRef);
|
|
192
|
+
if (pluginId) {
|
|
193
|
+
return pluginId;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const apiRefId = apiRef.id;
|
|
189
197
|
const [prefix, ...rest] = apiRefId.split(".");
|
|
190
198
|
if (!prefix) {
|
|
191
199
|
return apiRefId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiFactories.esm.js","sources":["../../src/wiring/apiFactories.ts"],"sourcesContent":["/*\n * Copyright 2023 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 ApiBlueprint,\n AnyApiFactory,\n ApiHolder,\n AppNode,\n FrontendFeature,\n featureFlagsApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { OpaqueFrontendPlugin } from '@internal/frontend';\nimport { instantiateAppNodeSubtree } from '../tree/instantiateAppNodeTree';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n isInternalFrontendModule,\n toInternalFrontendModule,\n} from '../../../frontend-plugin-api/src/wiring/createFrontendModule';\nimport { ErrorCollector } from './createErrorCollector';\nimport {\n FrontendApiRegistry,\n FrontendApiResolver,\n} from './FrontendApiRegistry';\nimport { type ExtensionPredicateContext } from './predicates';\n\nexport type ApiFactoryEntry = {\n node: AppNode;\n pluginId: string;\n factory: AnyApiFactory;\n};\n\n/**\n * Registers feature flag declarations on an already prepared API holder.\n *\n * This is primarily used when bootstrap reuses APIs from a provided session\n * state rather than building a fresh registry from bootstrap-visible factories.\n */\nexport function registerFeatureFlagDeclarationsInHolder(\n apis: ApiHolder,\n features: FrontendFeature[],\n collector: ErrorCollector,\n) {\n const featureFlagApi = apis.get(featureFlagsApiRef);\n if (featureFlagApi) {\n registerFeatureFlagDeclarations(featureFlagApi, features, collector);\n }\n}\n\n/**\n * Decorates the feature flags API factory so plugin and module declarations are\n * registered whenever that API is instantiated.\n */\nexport function wrapFeatureFlagApiFactory(\n factory: AnyApiFactory,\n features: FrontendFeature[],\n collector: ErrorCollector,\n) {\n if (factory.api.id !== featureFlagsApiRef.id) {\n return factory;\n }\n\n return {\n ...factory,\n factory(deps) {\n const featureFlagApi = factory.factory(\n deps,\n ) as typeof featureFlagsApiRef.T;\n registerFeatureFlagDeclarations(featureFlagApi, features, collector);\n return featureFlagApi;\n },\n } as AnyApiFactory;\n}\n\n/**\n * Reconciles deferred API factories into the finalized API registry.\n *\n * It preserves bootstrap-frozen APIs, allows safe deferred additions, and\n * reports cases where bootstrap-visible extensions relied on APIs that only\n * became available during finalization.\n */\nexport function syncFinalApiFactories(options: {\n deferredApiNodes: Iterable<AppNode>;\n appApiRegistry: FrontendApiRegistry;\n apiResolver: FrontendApiResolver;\n collector: ErrorCollector;\n features: FrontendFeature[];\n bootstrapApiFactoryEntries: ReadonlyMap<string, ApiFactoryEntry>;\n bootstrapMissingApiAccesses: Map<string, { node: AppNode; apiRefId: string }>;\n predicateContext: ExtensionPredicateContext;\n}) {\n const finalApiEntries = collectApiFactoryEntries({\n apiNodes: options.deferredApiNodes,\n collector: options.collector,\n predicateContext: options.predicateContext,\n entries: new Map(options.bootstrapApiFactoryEntries),\n });\n // Only newly introduced or still-safe overrides are registered here. Any\n // bootstrap-materialized API remains frozen for the lifetime of the app.\n const changedEntries = Array.from(finalApiEntries.values()).filter(entry => {\n const bootstrapEntry = options.bootstrapApiFactoryEntries.get(\n entry.factory.api.id,\n );\n if (!bootstrapEntry) {\n return true;\n }\n if (bootstrapEntry.factory === entry.factory) {\n return false;\n }\n if (options.apiResolver.isMaterialized(entry.factory.api.id)) {\n options.collector.report({\n code: 'EXTENSION_BOOTSTRAP_API_OVERRIDE_IGNORED',\n message:\n `Extension '${entry.node.spec.id}' tried to override API ` +\n `'${entry.factory.api.id}' after it had already been materialized during bootstrap. ` +\n 'The bootstrap implementation was kept and the deferred override was ignored.',\n context: {\n node: entry.node,\n apiRefId: entry.factory.api.id,\n bootstrapNode: bootstrapEntry.node,\n pluginId: entry.pluginId,\n bootstrapPluginId: bootstrapEntry.pluginId,\n },\n });\n return false;\n }\n return true;\n });\n const changedFactories = changedEntries.map(entry =>\n wrapFeatureFlagApiFactory(\n entry.factory,\n options.features,\n options.collector,\n ),\n );\n options.appApiRegistry.setAll(changedFactories);\n options.apiResolver.invalidate(\n changedFactories.map(factory => factory.api.id),\n );\n for (const bootstrapAccess of options.bootstrapMissingApiAccesses.values()) {\n if (\n options.bootstrapApiFactoryEntries.has(bootstrapAccess.apiRefId) ||\n !finalApiEntries.has(bootstrapAccess.apiRefId)\n ) {\n continue;\n }\n\n options.collector.report({\n code: 'EXTENSION_BOOTSTRAP_API_UNAVAILABLE',\n message:\n `Extension '${bootstrapAccess.node.spec.id}' tried to access API ` +\n `'${bootstrapAccess.apiRefId}' during bootstrap before it was available. ` +\n 'That API became available during finalization, so bootstrap-visible extensions must not depend on deferred APIs.',\n context: {\n node: bootstrapAccess.node,\n apiRefId: bootstrapAccess.apiRefId,\n },\n });\n }\n}\n\nconst EMPTY_API_HOLDER: ApiHolder = {\n get() {\n return undefined;\n },\n};\n\nfunction registerFeatureFlagDeclarations(\n featureFlagApi: typeof featureFlagsApiRef.T,\n features: FrontendFeature[],\n collector: ErrorCollector,\n) {\n for (const feature of features) {\n let pluginId: string | undefined;\n let flags: Array<{ name: string; description?: string }> | undefined;\n let source: string | undefined;\n\n if (OpaqueFrontendPlugin.isType(feature)) {\n pluginId = feature.id;\n flags = OpaqueFrontendPlugin.toInternal(feature).featureFlags;\n source = 'Plugin';\n } else if (isInternalFrontendModule(feature)) {\n pluginId = feature.pluginId;\n flags = toInternalFrontendModule(feature).featureFlags;\n source = 'Module for plugin';\n }\n\n if (pluginId && flags && source) {\n for (const flag of flags) {\n try {\n featureFlagApi.registerFlag({\n name: flag.name,\n description: flag.description,\n pluginId,\n });\n } catch (error) {\n collector.report({\n code: 'FEATURE_FLAG_INVALID',\n message: `${source} '${pluginId}' declared invalid feature flag '${flag.name}': ${error}`,\n context: { pluginId, flagName: flag.name, error: error as Error },\n });\n }\n }\n }\n }\n}\n\n/**\n * Instantiates API extension subtrees in isolation and extracts the factories\n * they provide without mutating the live app tree.\n *\n * The collected entries are later used both for bootstrap registration and for\n * the finalization-time reconciliation of deferred API roots.\n */\nexport function collectApiFactoryEntries(options: {\n apiNodes: Iterable<AppNode>;\n collector: ErrorCollector;\n predicateContext?: ExtensionPredicateContext;\n entries?: Map<string, ApiFactoryEntry>;\n}): Map<string, ApiFactoryEntry> {\n const factoriesById = options.entries ?? new Map<string, ApiFactoryEntry>();\n for (const apiNode of options.apiNodes) {\n // API extensions are instantiated in isolation so we can inspect the\n // produced factories without mutating the live app tree.\n const detachedApiNode = instantiateAppNodeSubtree({\n rootNode: apiNode,\n apis: EMPTY_API_HOLDER,\n collector: options.collector,\n predicateContext: options.predicateContext,\n writeNodeInstances: false,\n reuseExistingInstances: false,\n });\n if (!detachedApiNode) {\n continue;\n }\n const apiFactory = detachedApiNode.instance?.getData(\n ApiBlueprint.dataRefs.factory,\n );\n if (apiFactory) {\n const apiRefId = apiFactory.api.id;\n const ownerId = getApiOwnerId(apiRefId);\n const pluginId = apiNode.spec.plugin.pluginId ?? 'app';\n const existingFactory = factoriesById.get(apiRefId);\n\n // This allows modules to override factories provided by the plugin, but\n // it rejects API overrides from other plugins. In the event of a\n // conflict, the owning plugin is attempted to be inferred from the API\n // reference ID.\n if (existingFactory && existingFactory.pluginId !== pluginId) {\n const shouldReplace =\n ownerId === pluginId && existingFactory.pluginId !== ownerId;\n const acceptedPluginId = shouldReplace\n ? pluginId\n : existingFactory.pluginId;\n const rejectedPluginId = shouldReplace\n ? existingFactory.pluginId\n : pluginId;\n\n options.collector.report({\n code: 'API_FACTORY_CONFLICT',\n message: `API '${apiRefId}' is already provided by plugin '${acceptedPluginId}', cannot also be provided by '${rejectedPluginId}'.`,\n context: {\n node: apiNode,\n apiRefId,\n pluginId: rejectedPluginId,\n existingPluginId: acceptedPluginId,\n },\n });\n if (shouldReplace) {\n factoriesById.set(apiRefId, {\n pluginId,\n node: apiNode,\n factory: apiFactory,\n });\n }\n continue;\n }\n\n factoriesById.set(apiRefId, {\n pluginId,\n node: apiNode,\n factory: apiFactory,\n });\n } else {\n options.collector.report({\n code: 'API_EXTENSION_INVALID',\n message: `API extension '${apiNode.spec.id}' did not output an API factory`,\n context: {\n node: apiNode,\n },\n });\n }\n }\n\n return factoriesById;\n}\n\n// TODO(Rugvip): It would be good if this was more explicit, but I think that\n// might need to wait for some future update for API factories.\nfunction getApiOwnerId(apiRefId: string): string {\n const [prefix, ...rest] = apiRefId.split('.');\n if (!prefix) {\n return apiRefId;\n }\n if (prefix === 'core') {\n return 'app';\n }\n if (prefix === 'plugin' && rest[0]) {\n return rest[0];\n }\n return prefix;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"apiFactories.esm.js","sources":["../../src/wiring/apiFactories.ts"],"sourcesContent":["/*\n * Copyright 2023 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 ApiBlueprint,\n AnyApiFactory,\n ApiHolder,\n AppNode,\n FrontendFeature,\n featureFlagsApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { OpaqueApiRef, OpaqueFrontendPlugin } from '@internal/frontend';\nimport { instantiateAppNodeSubtree } from '../tree/instantiateAppNodeTree';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n isInternalFrontendModule,\n toInternalFrontendModule,\n} from '../../../frontend-plugin-api/src/wiring/createFrontendModule';\nimport { ErrorCollector } from './createErrorCollector';\nimport {\n FrontendApiRegistry,\n FrontendApiResolver,\n} from './FrontendApiRegistry';\nimport { type ExtensionPredicateContext } from './predicates';\n\nexport type ApiFactoryEntry = {\n node: AppNode;\n pluginId: string;\n factory: AnyApiFactory;\n};\n\n/**\n * Registers feature flag declarations on an already prepared API holder.\n *\n * This is primarily used when bootstrap reuses APIs from a provided session\n * state rather than building a fresh registry from bootstrap-visible factories.\n */\nexport function registerFeatureFlagDeclarationsInHolder(\n apis: ApiHolder,\n features: FrontendFeature[],\n collector: ErrorCollector,\n) {\n const featureFlagApi = apis.get(featureFlagsApiRef);\n if (featureFlagApi) {\n registerFeatureFlagDeclarations(featureFlagApi, features, collector);\n }\n}\n\n/**\n * Decorates the feature flags API factory so plugin and module declarations are\n * registered whenever that API is instantiated.\n */\nexport function wrapFeatureFlagApiFactory(\n factory: AnyApiFactory,\n features: FrontendFeature[],\n collector: ErrorCollector,\n) {\n if (factory.api.id !== featureFlagsApiRef.id) {\n return factory;\n }\n\n return {\n ...factory,\n factory(deps) {\n const featureFlagApi = factory.factory(\n deps,\n ) as typeof featureFlagsApiRef.T;\n registerFeatureFlagDeclarations(featureFlagApi, features, collector);\n return featureFlagApi;\n },\n } as AnyApiFactory;\n}\n\n/**\n * Reconciles deferred API factories into the finalized API registry.\n *\n * It preserves bootstrap-frozen APIs, allows safe deferred additions, and\n * reports cases where bootstrap-visible extensions relied on APIs that only\n * became available during finalization.\n */\nexport function syncFinalApiFactories(options: {\n deferredApiNodes: Iterable<AppNode>;\n appApiRegistry: FrontendApiRegistry;\n apiResolver: FrontendApiResolver;\n collector: ErrorCollector;\n features: FrontendFeature[];\n bootstrapApiFactoryEntries: ReadonlyMap<string, ApiFactoryEntry>;\n bootstrapMissingApiAccesses: Map<string, { node: AppNode; apiRefId: string }>;\n predicateContext: ExtensionPredicateContext;\n}) {\n const finalApiEntries = collectApiFactoryEntries({\n apiNodes: options.deferredApiNodes,\n collector: options.collector,\n predicateContext: options.predicateContext,\n entries: new Map(options.bootstrapApiFactoryEntries),\n });\n // Only newly introduced or still-safe overrides are registered here. Any\n // bootstrap-materialized API remains frozen for the lifetime of the app.\n const changedEntries = Array.from(finalApiEntries.values()).filter(entry => {\n const bootstrapEntry = options.bootstrapApiFactoryEntries.get(\n entry.factory.api.id,\n );\n if (!bootstrapEntry) {\n return true;\n }\n if (bootstrapEntry.factory === entry.factory) {\n return false;\n }\n if (options.apiResolver.isMaterialized(entry.factory.api.id)) {\n options.collector.report({\n code: 'EXTENSION_BOOTSTRAP_API_OVERRIDE_IGNORED',\n message:\n `Extension '${entry.node.spec.id}' tried to override API ` +\n `'${entry.factory.api.id}' after it had already been materialized during bootstrap. ` +\n 'The bootstrap implementation was kept and the deferred override was ignored.',\n context: {\n node: entry.node,\n apiRefId: entry.factory.api.id,\n bootstrapNode: bootstrapEntry.node,\n pluginId: entry.pluginId,\n bootstrapPluginId: bootstrapEntry.pluginId,\n },\n });\n return false;\n }\n return true;\n });\n const changedFactories = changedEntries.map(entry =>\n wrapFeatureFlagApiFactory(\n entry.factory,\n options.features,\n options.collector,\n ),\n );\n options.appApiRegistry.setAll(changedFactories);\n options.apiResolver.invalidate(\n changedFactories.map(factory => factory.api.id),\n );\n for (const bootstrapAccess of options.bootstrapMissingApiAccesses.values()) {\n if (\n options.bootstrapApiFactoryEntries.has(bootstrapAccess.apiRefId) ||\n !finalApiEntries.has(bootstrapAccess.apiRefId)\n ) {\n continue;\n }\n\n options.collector.report({\n code: 'EXTENSION_BOOTSTRAP_API_UNAVAILABLE',\n message:\n `Extension '${bootstrapAccess.node.spec.id}' tried to access API ` +\n `'${bootstrapAccess.apiRefId}' during bootstrap before it was available. ` +\n 'That API became available during finalization, so bootstrap-visible extensions must not depend on deferred APIs.',\n context: {\n node: bootstrapAccess.node,\n apiRefId: bootstrapAccess.apiRefId,\n },\n });\n }\n}\n\nconst EMPTY_API_HOLDER: ApiHolder = {\n get() {\n return undefined;\n },\n};\n\nfunction registerFeatureFlagDeclarations(\n featureFlagApi: typeof featureFlagsApiRef.T,\n features: FrontendFeature[],\n collector: ErrorCollector,\n) {\n for (const feature of features) {\n let pluginId: string | undefined;\n let flags: Array<{ name: string; description?: string }> | undefined;\n let source: string | undefined;\n\n if (OpaqueFrontendPlugin.isType(feature)) {\n pluginId = feature.id;\n flags = OpaqueFrontendPlugin.toInternal(feature).featureFlags;\n source = 'Plugin';\n } else if (isInternalFrontendModule(feature)) {\n pluginId = feature.pluginId;\n flags = toInternalFrontendModule(feature).featureFlags;\n source = 'Module for plugin';\n }\n\n if (pluginId && flags && source) {\n for (const flag of flags) {\n try {\n featureFlagApi.registerFlag({\n name: flag.name,\n description: flag.description,\n pluginId,\n });\n } catch (error) {\n collector.report({\n code: 'FEATURE_FLAG_INVALID',\n message: `${source} '${pluginId}' declared invalid feature flag '${flag.name}': ${error}`,\n context: { pluginId, flagName: flag.name, error: error as Error },\n });\n }\n }\n }\n }\n}\n\n/**\n * Instantiates API extension subtrees in isolation and extracts the factories\n * they provide without mutating the live app tree.\n *\n * The collected entries are later used both for bootstrap registration and for\n * the finalization-time reconciliation of deferred API roots.\n */\nexport function collectApiFactoryEntries(options: {\n apiNodes: Iterable<AppNode>;\n collector: ErrorCollector;\n predicateContext?: ExtensionPredicateContext;\n entries?: Map<string, ApiFactoryEntry>;\n}): Map<string, ApiFactoryEntry> {\n const factoriesById = options.entries ?? new Map<string, ApiFactoryEntry>();\n for (const apiNode of options.apiNodes) {\n // API extensions are instantiated in isolation so we can inspect the\n // produced factories without mutating the live app tree.\n const detachedApiNode = instantiateAppNodeSubtree({\n rootNode: apiNode,\n apis: EMPTY_API_HOLDER,\n collector: options.collector,\n predicateContext: options.predicateContext,\n writeNodeInstances: false,\n reuseExistingInstances: false,\n });\n if (!detachedApiNode) {\n continue;\n }\n const apiFactory = detachedApiNode.instance?.getData(\n ApiBlueprint.dataRefs.factory,\n );\n if (apiFactory) {\n const apiRefId = apiFactory.api.id;\n const ownerId = getApiOwnerId(apiFactory.api);\n const pluginId = apiNode.spec.plugin.pluginId ?? 'app';\n const existingFactory = factoriesById.get(apiRefId);\n\n // This allows modules to override factories provided by the plugin, but\n // it rejects API overrides from other plugins. In the event of a\n // conflict, the owning plugin is inferred from explicit ownership\n // metadata or the API reference ID.\n if (existingFactory && existingFactory.pluginId !== pluginId) {\n const shouldReplace =\n ownerId === pluginId && existingFactory.pluginId !== ownerId;\n const acceptedPluginId = shouldReplace\n ? pluginId\n : existingFactory.pluginId;\n const rejectedPluginId = shouldReplace\n ? existingFactory.pluginId\n : pluginId;\n\n options.collector.report({\n code: 'API_FACTORY_CONFLICT',\n message: `API '${apiRefId}' is already provided by plugin '${acceptedPluginId}', cannot also be provided by '${rejectedPluginId}'.`,\n context: {\n node: apiNode,\n apiRefId,\n pluginId: rejectedPluginId,\n existingPluginId: acceptedPluginId,\n },\n });\n if (shouldReplace) {\n factoriesById.set(apiRefId, {\n pluginId,\n node: apiNode,\n factory: apiFactory,\n });\n }\n continue;\n }\n\n factoriesById.set(apiRefId, {\n pluginId,\n node: apiNode,\n factory: apiFactory,\n });\n } else {\n options.collector.report({\n code: 'API_EXTENSION_INVALID',\n message: `API extension '${apiNode.spec.id}' did not output an API factory`,\n context: {\n node: apiNode,\n },\n });\n }\n }\n\n return factoriesById;\n}\n\n// TODO(Rugvip): It would be good if this was more explicit, but I think that\n// might need to wait for some future update for API factories.\nfunction getApiOwnerId(apiRef: { id: string }): string {\n if (OpaqueApiRef.isType(apiRef)) {\n const { pluginId } = OpaqueApiRef.toInternal(apiRef);\n if (pluginId) {\n return pluginId;\n }\n }\n\n const apiRefId = apiRef.id;\n const [prefix, ...rest] = apiRefId.split('.');\n if (!prefix) {\n return apiRefId;\n }\n if (prefix === 'core') {\n return 'app';\n }\n if (prefix === 'plugin' && rest[0]) {\n return rest[0];\n }\n return prefix;\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/frontend-app-api",
|
|
3
|
-
"version": "0.16.7-next.
|
|
3
|
+
"version": "0.16.7-next.1",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "web-library"
|
|
6
6
|
},
|
|
@@ -33,29 +33,29 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@backstage/config": "1.3.8",
|
|
36
|
-
"@backstage/core-app-api": "1.20.4-next.
|
|
37
|
-
"@backstage/core-plugin-api": "1.12.
|
|
36
|
+
"@backstage/core-app-api": "1.20.4-next.1",
|
|
37
|
+
"@backstage/core-plugin-api": "1.12.9-next.0",
|
|
38
38
|
"@backstage/errors": "1.3.1",
|
|
39
39
|
"@backstage/filter-predicates": "0.1.4",
|
|
40
|
-
"@backstage/frontend-defaults": "0.5.5-next.
|
|
41
|
-
"@backstage/frontend-plugin-api": "0.
|
|
40
|
+
"@backstage/frontend-defaults": "0.5.5-next.1",
|
|
41
|
+
"@backstage/frontend-plugin-api": "0.18.0-next.0",
|
|
42
42
|
"@backstage/types": "1.2.2",
|
|
43
43
|
"@backstage/version-bridge": "1.0.12",
|
|
44
|
-
"lodash": "^4.17.21"
|
|
45
|
-
"zod": "^3.25.76 || ^4.0.0"
|
|
44
|
+
"lodash": "^4.17.21"
|
|
46
45
|
},
|
|
47
46
|
"devDependencies": {
|
|
48
|
-
"@backstage/cli": "0.36.
|
|
49
|
-
"@backstage/frontend-test-utils": "0.6.3-next.
|
|
50
|
-
"@backstage/plugin-app": "0.5.2-next.
|
|
47
|
+
"@backstage/cli": "0.36.5-next.1",
|
|
48
|
+
"@backstage/frontend-test-utils": "0.6.3-next.1",
|
|
49
|
+
"@backstage/plugin-app": "0.5.2-next.2",
|
|
51
50
|
"@backstage/plugin-permission-common": "0.9.9",
|
|
52
|
-
"@backstage/test-utils": "1.7.21-next.
|
|
51
|
+
"@backstage/test-utils": "1.7.21-next.1",
|
|
53
52
|
"@testing-library/jest-dom": "^6.0.0",
|
|
54
53
|
"@testing-library/react": "^16.0.0",
|
|
55
54
|
"@types/react": "^18.0.0",
|
|
56
55
|
"react": "^18.0.2",
|
|
57
56
|
"react-dom": "^18.0.2",
|
|
58
|
-
"react-router-dom": "^6.30.2"
|
|
57
|
+
"react-router-dom": "^6.30.2",
|
|
58
|
+
"zod": "^4.0.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@types/react": "^17.0.0 || ^18.0.0",
|