@backstage/frontend-app-api 0.16.0-next.1 → 0.16.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/frontend-internal/src/wiring/InternalExtensionDefinition.esm.js.map +1 -1
  3. package/dist/frontend-internal/src/wiring/InternalFrontendPlugin.esm.js.map +1 -1
  4. package/dist/frontend-plugin-api/src/wiring/createFrontendModule.esm.js.map +1 -1
  5. package/dist/frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js.map +1 -1
  6. package/dist/index.d.ts +143 -26
  7. package/dist/index.esm.js +1 -0
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/routing/RouteAliasResolver.esm.js +0 -2
  10. package/dist/routing/RouteAliasResolver.esm.js.map +1 -1
  11. package/dist/routing/RouteResolver.esm.js +1 -1
  12. package/dist/routing/resolveRouteBindings.esm.js +2 -0
  13. package/dist/routing/resolveRouteBindings.esm.js.map +1 -1
  14. package/dist/tree/instantiateAppNodeTree.esm.js +72 -15
  15. package/dist/tree/instantiateAppNodeTree.esm.js.map +1 -1
  16. package/dist/tree/resolveAppNodeSpecs.esm.js +50 -9
  17. package/dist/tree/resolveAppNodeSpecs.esm.js.map +1 -1
  18. package/dist/wiring/FrontendApiRegistry.esm.js +92 -0
  19. package/dist/wiring/FrontendApiRegistry.esm.js.map +1 -0
  20. package/dist/wiring/apiFactories.esm.js +185 -0
  21. package/dist/wiring/apiFactories.esm.js.map +1 -0
  22. package/dist/wiring/createErrorCollector.esm.js.map +1 -1
  23. package/dist/wiring/createPluginInfoAttacher.esm.js.map +1 -1
  24. package/dist/wiring/createSpecializedApp.esm.js +11 -285
  25. package/dist/wiring/createSpecializedApp.esm.js.map +1 -1
  26. package/dist/wiring/phaseApis.esm.js +161 -0
  27. package/dist/wiring/phaseApis.esm.js.map +1 -0
  28. package/dist/wiring/predicates.esm.js +116 -0
  29. package/dist/wiring/predicates.esm.js.map +1 -0
  30. package/dist/wiring/prepareSpecializedApp.esm.js +516 -0
  31. package/dist/wiring/prepareSpecializedApp.esm.js.map +1 -0
  32. package/dist/wiring/treeLifecycle.esm.js +186 -0
  33. package/dist/wiring/treeLifecycle.esm.js.map +1 -0
  34. package/package.json +16 -14
  35. package/dist/core-app-api/src/apis/system/ApiRegistry.esm.js +0 -50
  36. package/dist/core-app-api/src/apis/system/ApiRegistry.esm.js.map +0 -1
@@ -0,0 +1,186 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { coreExtensionData } from '@backstage/frontend-plugin-api';
3
+ import { instantiateAndInitializePhaseTree } from './phaseApis.esm.js';
4
+
5
+ function createBootstrapApp(options) {
6
+ const signInPageNode = getAppRootNode(options.tree)?.edges.attachments.get(
7
+ "signInPage"
8
+ )?.[0];
9
+ instantiateAndInitializePhaseTree({
10
+ tree: options.tree,
11
+ apis: options.apis,
12
+ collector: options.collector,
13
+ extensionFactoryMiddleware: options.extensionFactoryMiddleware,
14
+ routeResolutionApi: options.routeResolutionApi,
15
+ appTreeApi: options.appTreeApi,
16
+ routeRefsById: options.routeRefsById,
17
+ stopAtAttachment: ({ node, input }) => isSessionBoundaryAttachment(node, input),
18
+ skipChild: options.skipBootstrapChild,
19
+ onMissingApi: options.onMissingApi
20
+ });
21
+ const element = options.tree.root.instance?.getData(
22
+ coreExtensionData.reactElement
23
+ );
24
+ if (!element) {
25
+ throw new Error("Expected bootstrap tree to expose a root element");
26
+ }
27
+ return {
28
+ bootstrapApp: {
29
+ element,
30
+ tree: options.tree
31
+ },
32
+ requiresSignIn: !options.disableSignIn && options.hasSignInPage(signInPageNode)
33
+ };
34
+ }
35
+ function classifyBootstrapTree(options) {
36
+ const apiNodes = options.tree.root.edges.attachments.get("apis") ?? [];
37
+ const deferredApiRoots = new Set(
38
+ apiNodes.filter((apiNode) => subtreeContainsPredicate(apiNode))
39
+ );
40
+ const appRootElementNodes = getAppRootNode(options.tree)?.edges.attachments.get("elements") ?? [];
41
+ const deferredElementRoots = new Set(
42
+ appRootElementNodes.filter(
43
+ (elementNode) => subtreeContainsPredicate(elementNode)
44
+ )
45
+ );
46
+ const deferredRoots = /* @__PURE__ */ new Set([
47
+ ...deferredApiRoots,
48
+ ...deferredElementRoots
49
+ ]);
50
+ const bootstrapNodes = collectBootstrapVisibleNodes(options.tree, {
51
+ deferredRoots
52
+ });
53
+ for (const node of bootstrapNodes) {
54
+ if (node.spec.if === void 0) {
55
+ continue;
56
+ }
57
+ options.collector.report({
58
+ code: "EXTENSION_BOOTSTRAP_PREDICATE_IGNORED",
59
+ message: `Extension '${node.spec.id}' uses 'if' during bootstrap, so the predicate was ignored. Move it behind 'app/root.children', onto a deferred 'app/root.elements' subtree, or into an API subtree.`,
60
+ context: {
61
+ node
62
+ }
63
+ });
64
+ node.spec.if = void 0;
65
+ }
66
+ return {
67
+ deferredApiRoots,
68
+ deferredElementRoots,
69
+ deferredRoots
70
+ };
71
+ }
72
+ function prepareFinalizedTree(options) {
73
+ for (const appRootNode of getFinalizationBoundaryNodes(options.tree)) {
74
+ const attachments = appRootNode.edges.attachments;
75
+ attachments.delete("signInPage");
76
+ }
77
+ }
78
+ function clearFinalizationBoundaryInstances(tree) {
79
+ clearNodeInstance(tree.root);
80
+ const visited = /* @__PURE__ */ new Set();
81
+ function visit(node) {
82
+ if (visited.has(node)) {
83
+ return;
84
+ }
85
+ visited.add(node);
86
+ clearNodeInstance(node);
87
+ for (const [input, children] of node.edges.attachments) {
88
+ if (node.spec.id === "app/root" && input === "elements") {
89
+ continue;
90
+ }
91
+ for (const child of children) {
92
+ visit(child);
93
+ }
94
+ }
95
+ }
96
+ for (const appRootNode of getFinalizationBoundaryNodes(tree)) {
97
+ visit(appRootNode);
98
+ }
99
+ }
100
+ function isSessionBoundaryAttachment(node, input) {
101
+ return node.spec.id === "app/root" && input === "children";
102
+ }
103
+ function attachThrowingFinalizationChild(tree, error) {
104
+ const bootstrapChildNode = getAppRootNode(tree)?.edges.attachments.get("children")?.[0];
105
+ if (!bootstrapChildNode) {
106
+ throw error;
107
+ }
108
+ function ThrowBootstrapError() {
109
+ throw error;
110
+ }
111
+ bootstrapChildNode.instance = {
112
+ getDataRefs() {
113
+ return [coreExtensionData.reactElement];
114
+ },
115
+ getData(dataRef) {
116
+ if (dataRef.id === coreExtensionData.reactElement.id) {
117
+ return /* @__PURE__ */ jsx(ThrowBootstrapError, {});
118
+ }
119
+ return void 0;
120
+ }
121
+ };
122
+ }
123
+ function getAppRootNode(tree) {
124
+ return tree.nodes.get("app/root");
125
+ }
126
+ function getFinalizationBoundaryNodes(tree) {
127
+ const nodes = /* @__PURE__ */ new Set();
128
+ const appRootNode = getAppRootNode(tree);
129
+ if (appRootNode) {
130
+ nodes.add(appRootNode);
131
+ }
132
+ const attachedAppRootNode = tree.root.edges.attachments.get("app")?.[0];
133
+ if (attachedAppRootNode) {
134
+ nodes.add(attachedAppRootNode);
135
+ }
136
+ return Array.from(nodes);
137
+ }
138
+ function clearNodeInstance(node) {
139
+ node.instance = void 0;
140
+ }
141
+ function collectBootstrapVisibleNodes(tree, options) {
142
+ const visibleNodes = /* @__PURE__ */ new Set();
143
+ function visit(node) {
144
+ if (visibleNodes.has(node)) {
145
+ return;
146
+ }
147
+ visibleNodes.add(node);
148
+ for (const [input, children] of node.edges.attachments) {
149
+ if (isSessionBoundaryAttachment(node, input)) {
150
+ continue;
151
+ }
152
+ for (const child of children) {
153
+ if (options?.deferredRoots?.has(child)) {
154
+ continue;
155
+ }
156
+ visit(child);
157
+ }
158
+ }
159
+ }
160
+ visit(tree.root);
161
+ return visibleNodes;
162
+ }
163
+ function subtreeContainsPredicate(root) {
164
+ const visited = /* @__PURE__ */ new Set();
165
+ function visit(node) {
166
+ if (visited.has(node)) {
167
+ return false;
168
+ }
169
+ visited.add(node);
170
+ if (node.spec.if !== void 0) {
171
+ return true;
172
+ }
173
+ for (const children of node.edges.attachments.values()) {
174
+ for (const child of children) {
175
+ if (visit(child)) {
176
+ return true;
177
+ }
178
+ }
179
+ }
180
+ return false;
181
+ }
182
+ return visit(root);
183
+ }
184
+
185
+ export { attachThrowingFinalizationChild, classifyBootstrapTree, clearFinalizationBoundaryInstances, createBootstrapApp, isSessionBoundaryAttachment, prepareFinalizedTree };
186
+ //# sourceMappingURL=treeLifecycle.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treeLifecycle.esm.js","sources":["../../src/wiring/treeLifecycle.tsx"],"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 ApiHolder,\n AppNode,\n AppNodeInstance,\n AppTree,\n coreExtensionData,\n ExtensionDataRef,\n ExtensionFactoryMiddleware,\n} from '@backstage/frontend-plugin-api';\nimport { FilterPredicate } from '@backstage/filter-predicates';\nimport { collectRouteIds } from '../routing/collectRouteIds';\nimport { ErrorCollector } from './createErrorCollector';\nimport {\n AppTreeApiProxy,\n instantiateAndInitializePhaseTree,\n RouteResolutionApiProxy,\n} from './phaseApis';\n\nexport type BootstrapClassification = {\n deferredApiRoots: Set<AppNode>;\n deferredElementRoots: Set<AppNode>;\n deferredRoots: Set<AppNode>;\n};\n\n/**\n * Instantiates the bootstrap-visible portion of the app tree and returns the\n * element that should be rendered while the prepared app is still incomplete.\n *\n * The bootstrap tree deliberately stops at the session boundary so sign-in and\n * other deferred content can be handled separately during finalization.\n */\nexport function createBootstrapApp(options: {\n tree: AppTree;\n apis: ApiHolder;\n collector: ErrorCollector;\n routeRefsById: ReturnType<typeof collectRouteIds>;\n routeResolutionApi: RouteResolutionApiProxy;\n appTreeApi: AppTreeApiProxy;\n extensionFactoryMiddleware?: ExtensionFactoryMiddleware;\n disableSignIn?: boolean;\n skipBootstrapChild?(ctx: {\n node: AppNode;\n input: string;\n child: AppNode;\n }): boolean;\n onMissingApi?(ctx: { node: AppNode; apiRefId: string }): void;\n hasSignInPage(node?: AppNode): boolean;\n}): {\n bootstrapApp: { element: JSX.Element; tree: AppTree };\n requiresSignIn: boolean;\n} {\n const signInPageNode = getAppRootNode(options.tree)?.edges.attachments.get(\n 'signInPage',\n )?.[0];\n\n instantiateAndInitializePhaseTree({\n tree: options.tree,\n apis: options.apis,\n collector: options.collector,\n extensionFactoryMiddleware: options.extensionFactoryMiddleware,\n routeResolutionApi: options.routeResolutionApi,\n appTreeApi: options.appTreeApi,\n routeRefsById: options.routeRefsById,\n stopAtAttachment: ({ node, input }) =>\n isSessionBoundaryAttachment(node, input),\n skipChild: options.skipBootstrapChild,\n onMissingApi: options.onMissingApi,\n });\n\n const element = options.tree.root.instance?.getData(\n coreExtensionData.reactElement,\n );\n if (!element) {\n throw new Error('Expected bootstrap tree to expose a root element');\n }\n\n return {\n bootstrapApp: {\n element,\n tree: options.tree,\n },\n requiresSignIn:\n !options.disableSignIn && options.hasSignInPage(signInPageNode),\n };\n}\n\n/**\n * Splits the app tree into bootstrap-visible and deferred regions.\n *\n * Predicate-gated roots are deferred to finalization, while any predicate that\n * still leaks into the bootstrap-visible region is reported and ignored.\n */\nexport function classifyBootstrapTree(options: {\n tree: AppTree;\n collector: ErrorCollector;\n}): BootstrapClassification {\n const apiNodes = options.tree.root.edges.attachments.get('apis') ?? [];\n const deferredApiRoots = new Set(\n apiNodes.filter(apiNode => subtreeContainsPredicate(apiNode)),\n );\n const appRootElementNodes =\n getAppRootNode(options.tree)?.edges.attachments.get('elements') ?? [];\n const deferredElementRoots = new Set(\n appRootElementNodes.filter(elementNode =>\n subtreeContainsPredicate(elementNode),\n ),\n );\n const deferredRoots = new Set<AppNode>([\n ...deferredApiRoots,\n ...deferredElementRoots,\n ]);\n const bootstrapNodes = collectBootstrapVisibleNodes(options.tree, {\n deferredRoots,\n });\n\n for (const node of bootstrapNodes) {\n if (node.spec.if === undefined) {\n continue;\n }\n\n options.collector.report({\n code: 'EXTENSION_BOOTSTRAP_PREDICATE_IGNORED',\n message:\n `Extension '${node.spec.id}' uses 'if' during bootstrap, so the predicate was ignored. ` +\n \"Move it behind 'app/root.children', onto a deferred 'app/root.elements' subtree, or into an API subtree.\",\n context: {\n node,\n },\n });\n (node.spec as typeof node.spec & { if?: FilterPredicate }).if = undefined;\n }\n\n return {\n deferredApiRoots,\n deferredElementRoots,\n deferredRoots,\n };\n}\n\n/**\n * Prepares the app tree for finalization by removing the bootstrap-only\n * sign-in attachment from the app root boundary.\n */\nexport function prepareFinalizedTree(options: { tree: AppTree }) {\n for (const appRootNode of getFinalizationBoundaryNodes(options.tree)) {\n const attachments = appRootNode.edges.attachments as Map<string, AppNode[]>;\n attachments.delete('signInPage');\n }\n}\n\n/**\n * Clears instances inside the finalization boundary so those nodes can be\n * re-instantiated with finalized predicate context and API availability.\n */\nexport function clearFinalizationBoundaryInstances(tree: AppTree) {\n clearNodeInstance(tree.root);\n\n const visited = new Set<AppNode>();\n function visit(node: AppNode) {\n if (visited.has(node)) {\n return;\n }\n visited.add(node);\n clearNodeInstance(node);\n\n for (const [input, children] of node.edges.attachments) {\n // app/root.elements is allowed to keep its bootstrap instances so we only\n // re-run the parts of the boundary that actually change at finalization.\n if (node.spec.id === 'app/root' && input === 'elements') {\n continue;\n }\n\n for (const child of children) {\n visit(child);\n }\n }\n }\n\n for (const appRootNode of getFinalizationBoundaryNodes(tree)) {\n visit(appRootNode);\n }\n}\n\n/**\n * Identifies the attachment that separates bootstrap rendering from the\n * children that are deferred until finalization.\n */\nexport function isSessionBoundaryAttachment(node: AppNode, input: string) {\n return node.spec.id === 'app/root' && input === 'children';\n}\n\n/**\n * Injects a synthetic finalization child that throws the captured bootstrap\n * error when rendered.\n *\n * This lets the finalized tree reuse the normal app root error boundary rather\n * than introducing a separate error rendering path.\n */\nexport function attachThrowingFinalizationChild(tree: AppTree, error: Error) {\n const bootstrapChildNode =\n getAppRootNode(tree)?.edges.attachments.get('children')?.[0];\n if (!bootstrapChildNode) {\n throw error;\n }\n\n function ThrowBootstrapError(): never {\n throw error;\n }\n\n // This synthetic child gives the finalized tree a stable place to rethrow\n // bootstrap failures through the normal extension boundary stack.\n (bootstrapChildNode as AppNode & { instance?: AppNodeInstance }).instance = {\n getDataRefs() {\n return [coreExtensionData.reactElement];\n },\n getData<TValue>(dataRef: ExtensionDataRef<TValue>) {\n if (dataRef.id === coreExtensionData.reactElement.id) {\n return (<ThrowBootstrapError />) as TValue;\n }\n return undefined;\n },\n };\n}\n\nfunction getAppRootNode(tree: AppTree) {\n return tree.nodes.get('app/root');\n}\n\nfunction getFinalizationBoundaryNodes(tree: AppTree): AppNode[] {\n const nodes = new Set<AppNode>();\n const appRootNode = getAppRootNode(tree);\n if (appRootNode) {\n nodes.add(appRootNode);\n }\n const attachedAppRootNode = tree.root.edges.attachments.get('app')?.[0];\n if (attachedAppRootNode) {\n nodes.add(attachedAppRootNode);\n }\n return Array.from(nodes);\n}\n\nfunction clearNodeInstance(node: AppNode) {\n (node as AppNode & { instance?: AppNodeInstance }).instance = undefined;\n}\n\nfunction collectBootstrapVisibleNodes(\n tree: AppTree,\n options?: { deferredRoots?: Set<AppNode> },\n) {\n const visibleNodes = new Set<AppNode>();\n\n function visit(node: AppNode) {\n if (visibleNodes.has(node)) {\n return;\n }\n visibleNodes.add(node);\n\n for (const [input, children] of node.edges.attachments) {\n if (isSessionBoundaryAttachment(node, input)) {\n continue;\n }\n\n for (const child of children) {\n if (options?.deferredRoots?.has(child)) {\n continue;\n }\n visit(child);\n }\n }\n }\n\n visit(tree.root);\n\n return visibleNodes;\n}\n\nfunction subtreeContainsPredicate(root: AppNode) {\n const visited = new Set<AppNode>();\n\n function visit(node: AppNode): boolean {\n if (visited.has(node)) {\n return false;\n }\n visited.add(node);\n\n if (node.spec.if !== undefined) {\n return true;\n }\n\n for (const children of node.edges.attachments.values()) {\n for (const child of children) {\n if (visit(child)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n return visit(root);\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.0-next.1",
3
+ "version": "0.16.0",
4
4
  "backstage": {
5
5
  "role": "web-library"
6
6
  },
@@ -32,22 +32,24 @@
32
32
  "test": "backstage-cli package test"
33
33
  },
34
34
  "dependencies": {
35
- "@backstage/config": "1.3.6",
36
- "@backstage/core-app-api": "1.19.6-next.1",
37
- "@backstage/core-plugin-api": "1.12.4-next.1",
38
- "@backstage/errors": "1.2.7",
39
- "@backstage/frontend-defaults": "0.5.0-next.1",
40
- "@backstage/frontend-plugin-api": "0.15.0-next.1",
41
- "@backstage/types": "1.2.2",
42
- "@backstage/version-bridge": "1.0.12",
35
+ "@backstage/config": "^1.3.6",
36
+ "@backstage/core-app-api": "^1.19.6",
37
+ "@backstage/core-plugin-api": "^1.12.4",
38
+ "@backstage/errors": "^1.2.7",
39
+ "@backstage/filter-predicates": "^0.1.1",
40
+ "@backstage/frontend-defaults": "^0.5.0",
41
+ "@backstage/frontend-plugin-api": "^0.15.0",
42
+ "@backstage/types": "^1.2.2",
43
+ "@backstage/version-bridge": "^1.0.12",
43
44
  "lodash": "^4.17.21",
44
- "zod": "^3.25.76"
45
+ "zod": "^3.25.76 || ^4.0.0"
45
46
  },
46
47
  "devDependencies": {
47
- "@backstage/cli": "0.36.0-next.2",
48
- "@backstage/frontend-test-utils": "0.5.1-next.2",
49
- "@backstage/plugin-app": "0.4.1-next.2",
50
- "@backstage/test-utils": "1.7.16-next.0",
48
+ "@backstage/cli": "^0.36.0",
49
+ "@backstage/frontend-test-utils": "^0.5.1",
50
+ "@backstage/plugin-app": "^0.4.1",
51
+ "@backstage/plugin-permission-common": "^0.9.7",
52
+ "@backstage/test-utils": "^1.7.16",
51
53
  "@testing-library/jest-dom": "^6.0.0",
52
54
  "@testing-library/react": "^16.0.0",
53
55
  "@types/react": "^18.0.0",
@@ -1,50 +0,0 @@
1
- class ApiRegistryBuilder {
2
- apis = [];
3
- add(api, impl) {
4
- this.apis.push([api.id, impl]);
5
- return impl;
6
- }
7
- build() {
8
- return new ApiRegistry(new Map(this.apis));
9
- }
10
- }
11
- class ApiRegistry {
12
- constructor(apis) {
13
- this.apis = apis;
14
- }
15
- static builder() {
16
- return new ApiRegistryBuilder();
17
- }
18
- /**
19
- * Creates a new ApiRegistry with a list of API implementations.
20
- *
21
- * @param apis - A list of pairs mapping an ApiRef to its respective implementation
22
- */
23
- static from(apis) {
24
- return new ApiRegistry(new Map(apis.map(([api, impl]) => [api.id, impl])));
25
- }
26
- /**
27
- * Creates a new ApiRegistry with a single API implementation.
28
- *
29
- * @param api - ApiRef for the API to add
30
- * @param impl - Implementation of the API to add
31
- */
32
- static with(api, impl) {
33
- return new ApiRegistry(/* @__PURE__ */ new Map([[api.id, impl]]));
34
- }
35
- /**
36
- * Returns a new ApiRegistry with the provided API added to the existing ones.
37
- *
38
- * @param api - ApiRef for the API to add
39
- * @param impl - Implementation of the API to add
40
- */
41
- with(api, impl) {
42
- return new ApiRegistry(new Map([...this.apis, [api.id, impl]]));
43
- }
44
- get(api) {
45
- return this.apis.get(api.id);
46
- }
47
- }
48
-
49
- export { ApiRegistry };
50
- //# sourceMappingURL=ApiRegistry.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ApiRegistry.esm.js","sources":["../../../../../../core-app-api/src/apis/system/ApiRegistry.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 { ApiRef, ApiHolder } from '@backstage/core-plugin-api';\n\ntype ApiImpl<T = unknown> = readonly [ApiRef<T>, T];\n\n/** @internal */\nclass ApiRegistryBuilder {\n private apis: [string, unknown][] = [];\n\n add<T, I extends T>(api: ApiRef<T>, impl: I): I {\n this.apis.push([api.id, impl]);\n return impl;\n }\n\n build(): ApiRegistry {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n return new ApiRegistry(new Map(this.apis));\n }\n}\n\n/**\n * A registry for utility APIs.\n *\n * @internal\n */\nexport class ApiRegistry implements ApiHolder {\n static builder() {\n return new ApiRegistryBuilder();\n }\n\n /**\n * Creates a new ApiRegistry with a list of API implementations.\n *\n * @param apis - A list of pairs mapping an ApiRef to its respective implementation\n */\n static from(apis: ApiImpl[]) {\n return new ApiRegistry(new Map(apis.map(([api, impl]) => [api.id, impl])));\n }\n\n /**\n * Creates a new ApiRegistry with a single API implementation.\n *\n * @param api - ApiRef for the API to add\n * @param impl - Implementation of the API to add\n */\n static with<T>(api: ApiRef<T>, impl: T): ApiRegistry {\n return new ApiRegistry(new Map([[api.id, impl]]));\n }\n\n constructor(private readonly apis: Map<string, unknown>) {}\n\n /**\n * Returns a new ApiRegistry with the provided API added to the existing ones.\n *\n * @param api - ApiRef for the API to add\n * @param impl - Implementation of the API to add\n */\n with<T>(api: ApiRef<T>, impl: T): ApiRegistry {\n return new ApiRegistry(new Map([...this.apis, [api.id, impl]]));\n }\n\n get<T>(api: ApiRef<T>): T | undefined {\n return this.apis.get(api.id) as T | undefined;\n }\n}\n"],"names":[],"mappings":"AAqBA,MAAM,kBAAA,CAAmB;AAAA,EACf,OAA4B,EAAC;AAAA,EAErC,GAAA,CAAoB,KAAgB,IAAA,EAAY;AAC9C,IAAA,IAAA,CAAK,KAAK,IAAA,CAAK,CAAC,GAAA,CAAI,EAAA,EAAI,IAAI,CAAC,CAAA;AAC7B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,KAAA,GAAqB;AAEnB,IAAA,OAAO,IAAI,WAAA,CAAY,IAAI,GAAA,CAAI,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,EAC3C;AACF;AAOO,MAAM,WAAA,CAAiC;AAAA,EAwB5C,YAA6B,IAAA,EAA4B;AAA5B,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAA6B;AAAA,EAvB1D,OAAO,OAAA,GAAU;AACf,IAAA,OAAO,IAAI,kBAAA,EAAmB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,KAAK,IAAA,EAAiB;AAC3B,IAAA,OAAO,IAAI,WAAA,CAAY,IAAI,GAAA,CAAI,IAAA,CAAK,IAAI,CAAC,CAAC,GAAA,EAAK,IAAI,MAAM,CAAC,GAAA,CAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAA;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,IAAA,CAAQ,GAAA,EAAgB,IAAA,EAAsB;AACnD,IAAA,OAAO,IAAI,WAAA,iBAAY,IAAI,GAAA,CAAI,CAAC,CAAC,GAAA,CAAI,EAAA,EAAI,IAAI,CAAC,CAAC,CAAC,CAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,IAAA,CAAQ,KAAgB,IAAA,EAAsB;AAC5C,IAAA,OAAO,IAAI,WAAA,CAAY,IAAI,GAAA,CAAI,CAAC,GAAG,IAAA,CAAK,IAAA,EAAM,CAAC,GAAA,CAAI,EAAA,EAAI,IAAI,CAAC,CAAC,CAAC,CAAA;AAAA,EAChE;AAAA,EAEA,IAAO,GAAA,EAA+B;AACpC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA;AAAA,EAC7B;AACF;;;;"}