@backstage/core-compat-api 0.0.0-nightly-20240119021656 → 0.0.0-nightly-20240120021525
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 +4 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.esm.js +23 -10
- package/dist/index.esm.js.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# @backstage/core-compat-api
|
|
2
2
|
|
|
3
|
-
## 0.0.0-nightly-
|
|
3
|
+
## 0.0.0-nightly-20240120021525
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
7
|
- 1fa5041: The backwards compatibility provider will now use the new `ComponentsApi` and `IconsApi` when implementing the old `AppContext`.
|
|
8
|
+
- 7155c30: Added `convertLegacyRouteRefs` for bulk conversion of plugin routes.
|
|
9
|
+
- 2f2a1d2: Plugins converted by `convertLegacyApp` now have their `routes` and `externalRoutes` included as well, allowing them to be used to bind external routes in configuration.
|
|
8
10
|
- Updated dependencies
|
|
9
|
-
- @backstage/frontend-plugin-api@0.0.0-nightly-
|
|
11
|
+
- @backstage/frontend-plugin-api@0.0.0-nightly-20240120021525
|
|
10
12
|
- @backstage/core-app-api@1.11.3
|
|
11
13
|
- @backstage/core-plugin-api@1.8.2
|
|
12
14
|
- @backstage/version-bridge@1.0.7
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { FrontendFeature, RouteRef as RouteRef$1, SubRouteRef as SubRouteRef$1, ExternalRouteRef as ExternalRouteRef$1 } from '@backstage/frontend-plugin-api';
|
|
3
|
-
import {
|
|
3
|
+
import { RouteRef, SubRouteRef, ExternalRouteRef, AnyRouteRefParams } from '@backstage/core-plugin-api';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Wraps a React element in a bidirectional compatibility provider, allow APIs
|
|
@@ -14,6 +14,23 @@ declare function compatWrapper(element: ReactNode): React.JSX.Element;
|
|
|
14
14
|
/** @public */
|
|
15
15
|
declare function convertLegacyApp(rootElement: React.JSX.Element): FrontendFeature[];
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Converts a legacy route ref type to the new system.
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
type ToNewRouteRef<T extends RouteRef | SubRouteRef | ExternalRouteRef> = T extends RouteRef<infer IParams> ? RouteRef$1<IParams> : T extends SubRouteRef<infer IParams> ? SubRouteRef$1<IParams> : T extends ExternalRouteRef<infer IParams, infer IOptional> ? ExternalRouteRef$1<IParams, IOptional> : never;
|
|
23
|
+
/**
|
|
24
|
+
* Converts a collection of legacy route refs to the new system.
|
|
25
|
+
* This is particularly useful when defining plugin `routes` and `externalRoutes`.
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
declare function convertLegacyRouteRefs<TRefs extends {
|
|
30
|
+
[name in string]: RouteRef | SubRouteRef | ExternalRouteRef;
|
|
31
|
+
}>(refs: TRefs): {
|
|
32
|
+
[KName in keyof TRefs]: ToNewRouteRef<TRefs[KName]>;
|
|
33
|
+
};
|
|
17
34
|
/**
|
|
18
35
|
* A temporary helper to convert a legacy route ref to the new system.
|
|
19
36
|
*
|
|
@@ -42,4 +59,4 @@ declare function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(ref: S
|
|
|
42
59
|
*/
|
|
43
60
|
declare function convertLegacyRouteRef<TParams extends AnyRouteRefParams, TOptional extends boolean>(ref: ExternalRouteRef<TParams, TOptional>): ExternalRouteRef$1<TParams, TOptional>;
|
|
44
61
|
|
|
45
|
-
export { compatWrapper, convertLegacyApp, convertLegacyRouteRef };
|
|
62
|
+
export { ToNewRouteRef, compatWrapper, convertLegacyApp, convertLegacyRouteRef, convertLegacyRouteRefs };
|
package/dist/index.esm.js
CHANGED
|
@@ -159,6 +159,14 @@ function toInternalExternalRouteRef(resource) {
|
|
|
159
159
|
return r;
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
function convertLegacyRouteRefs(refs) {
|
|
163
|
+
return Object.fromEntries(
|
|
164
|
+
Object.entries(refs).map(([name, ref]) => [
|
|
165
|
+
name,
|
|
166
|
+
convertLegacyRouteRef(ref)
|
|
167
|
+
])
|
|
168
|
+
);
|
|
169
|
+
}
|
|
162
170
|
function convertLegacyRouteRef(ref) {
|
|
163
171
|
if ("$$type" in ref) {
|
|
164
172
|
return ref;
|
|
@@ -372,15 +380,20 @@ function collectLegacyRoutes(flatRoutesElement) {
|
|
|
372
380
|
}
|
|
373
381
|
);
|
|
374
382
|
return Array.from(pluginExtensions).map(
|
|
375
|
-
([plugin, extensions]) =>
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
383
|
+
([plugin, extensions]) => {
|
|
384
|
+
var _a, _b;
|
|
385
|
+
return createPlugin({
|
|
386
|
+
id: plugin.getId(),
|
|
387
|
+
extensions: [
|
|
388
|
+
...extensions,
|
|
389
|
+
...Array.from(plugin.getApis()).map(
|
|
390
|
+
(factory) => createApiExtension({ factory })
|
|
391
|
+
)
|
|
392
|
+
],
|
|
393
|
+
routes: convertLegacyRouteRefs((_a = plugin.routes) != null ? _a : {}),
|
|
394
|
+
externalRoutes: convertLegacyRouteRefs((_b = plugin.externalRoutes) != null ? _b : {})
|
|
395
|
+
});
|
|
396
|
+
}
|
|
384
397
|
);
|
|
385
398
|
}
|
|
386
399
|
|
|
@@ -479,5 +492,5 @@ function convertLegacyApp(rootElement) {
|
|
|
479
492
|
];
|
|
480
493
|
}
|
|
481
494
|
|
|
482
|
-
export { compatWrapper, convertLegacyApp, convertLegacyRouteRef };
|
|
495
|
+
export { compatWrapper, convertLegacyApp, convertLegacyRouteRef, convertLegacyRouteRefs };
|
|
483
496
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../../core-app-api/src/app/AppContext.tsx","../src/compatWrapper/BackwardsCompatProvider.tsx","../src/compatWrapper/ForwardsCompatProvider.tsx","../src/compatWrapper/compatWrapper.tsx","../../core-plugin-api/src/routing/types.ts","../../frontend-plugin-api/src/routing/RouteRef.ts","../../frontend-plugin-api/src/routing/SubRouteRef.ts","../../frontend-plugin-api/src/routing/ExternalRouteRef.ts","../src/convertLegacyRouteRef.ts","../src/collectLegacyRoutes.tsx","../src/convertLegacyApp.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 React, { PropsWithChildren } from 'react';\nimport {\n createVersionedValueMap,\n createVersionedContext,\n} from '@backstage/version-bridge';\nimport { AppContext as AppContextV1 } from './types';\n\nconst AppContext = createVersionedContext<{ 1: AppContextV1 }>('app-context');\n\ntype Props = {\n appContext: AppContextV1;\n};\n\nexport const AppContextProvider = ({\n appContext,\n children,\n}: PropsWithChildren<Props>) => {\n const versionedValue = createVersionedValueMap({ 1: appContext });\n\n return <AppContext.Provider value={versionedValue} children={children} />;\n};\n","/*\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 React, { useMemo } from 'react';\nimport { ReactNode } from 'react';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppContextProvider } from '../../../core-app-api/src/app/AppContext';\nimport {\n createPlugin as createNewPlugin,\n BackstagePlugin as NewBackstagePlugin,\n appTreeApiRef,\n componentsApiRef,\n coreComponentRefs,\n iconsApiRef,\n useApi,\n} from '@backstage/frontend-plugin-api';\nimport {\n AppComponents,\n IconComponent,\n BackstagePlugin as LegacyBackstagePlugin,\n} from '@backstage/core-plugin-api';\nimport { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\n// Make sure that we only convert each new plugin instance to its legacy equivalent once\nconst legacyPluginStore = getOrCreateGlobalSingleton(\n 'legacy-plugin-compatibility-store',\n () => new WeakMap<NewBackstagePlugin, LegacyBackstagePlugin>(),\n);\n\nfunction toLegacyPlugin(plugin: NewBackstagePlugin): LegacyBackstagePlugin {\n let legacy = legacyPluginStore.get(plugin);\n if (legacy) {\n return legacy;\n }\n\n const errorMsg = 'Not implemented in legacy plugin compatibility layer';\n const notImplemented = () => {\n throw new Error(errorMsg);\n };\n\n legacy = {\n getId(): string {\n return plugin.id;\n },\n get routes() {\n return {};\n },\n get externalRoutes() {\n return {};\n },\n getApis: notImplemented,\n getFeatureFlags: notImplemented,\n provide: notImplemented,\n };\n\n legacyPluginStore.set(plugin, legacy);\n return legacy;\n}\n\n// TODO: Currently a very naive implementation, may need some more work\nfunction toNewPlugin(plugin: LegacyBackstagePlugin): NewBackstagePlugin {\n return createNewPlugin({\n id: plugin.getId(),\n });\n}\n\n// Recreates the old AppContext APIs using the various new APIs that replaced it\nfunction LegacyAppContextProvider(props: { children: ReactNode }) {\n const appTreeApi = useApi(appTreeApiRef);\n const componentsApi = useApi(componentsApiRef);\n const iconsApi = useApi(iconsApiRef);\n\n const appContext = useMemo(() => {\n const { tree } = appTreeApi.getTree();\n\n let gatheredPlugins: LegacyBackstagePlugin[] | undefined = undefined;\n\n const ErrorBoundaryFallback = componentsApi.getComponent(\n coreComponentRefs.errorBoundaryFallback,\n );\n const ErrorBoundaryFallbackWrapper: AppComponents['ErrorBoundaryFallback'] =\n ({ plugin, ...rest }) => (\n <ErrorBoundaryFallback\n {...rest}\n plugin={plugin && toNewPlugin(plugin)}\n />\n );\n\n return {\n getPlugins(): LegacyBackstagePlugin[] {\n if (gatheredPlugins) {\n return gatheredPlugins;\n }\n\n const pluginSet = new Set<LegacyBackstagePlugin>();\n for (const node of tree.nodes.values()) {\n const plugin = node.spec.source;\n if (plugin) {\n pluginSet.add(toLegacyPlugin(plugin));\n }\n }\n gatheredPlugins = Array.from(pluginSet);\n\n return gatheredPlugins;\n },\n\n getSystemIcon(key: string): IconComponent | undefined {\n return iconsApi.getIcon(key);\n },\n\n getSystemIcons(): Record<string, IconComponent> {\n return Object.fromEntries(\n iconsApi.listIconKeys().map(key => [key, iconsApi.getIcon(key)!]),\n );\n },\n\n getComponents(): AppComponents {\n return {\n NotFoundErrorPage: componentsApi.getComponent(\n coreComponentRefs.notFoundErrorPage,\n ),\n BootErrorPage() {\n throw new Error(\n 'The BootErrorPage app component should not be accessed by plugins',\n );\n },\n Progress: componentsApi.getComponent(coreComponentRefs.progress),\n Router() {\n throw new Error(\n 'The Router app component should not be accessed by plugins',\n );\n },\n ErrorBoundaryFallback: ErrorBoundaryFallbackWrapper,\n };\n },\n };\n }, [appTreeApi, componentsApi, iconsApi]);\n\n return (\n <AppContextProvider appContext={appContext}>\n {props.children}\n </AppContextProvider>\n );\n}\n\nexport function BackwardsCompatProvider(props: { children: ReactNode }) {\n return <LegacyAppContextProvider>{props.children}</LegacyAppContextProvider>;\n}\n","/*\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 React from 'react';\nimport { ReactNode } from 'react';\n\nexport function ForwardsCompatProvider(props: { children: ReactNode }) {\n // TODO(Rugvip): Implement\n return <>{props.children}</>;\n}\n","/*\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 React from 'react';\nimport { useVersionedContext } from '@backstage/version-bridge';\nimport { ReactNode } from 'react';\nimport { BackwardsCompatProvider } from './BackwardsCompatProvider';\nimport { ForwardsCompatProvider } from './ForwardsCompatProvider';\n\nfunction BidirectionalCompatProvider(props: { children: ReactNode }) {\n const isInNewApp = !useVersionedContext<{ 1: unknown }>('app-context');\n\n if (isInNewApp) {\n return <BackwardsCompatProvider {...props} />;\n }\n\n return <ForwardsCompatProvider {...props} />;\n}\n\n/**\n * Wraps a React element in a bidirectional compatibility provider, allow APIs\n * from `@backstage/core-plugin-api` to be used in an app from `@backstage/frontend-app-api`,\n * and APIs from `@backstage/frontend-plugin-api` to be used in an app from `@backstage/core-app-api`.\n *\n * @public\n */\nexport function compatWrapper(element: ReactNode) {\n return <BidirectionalCompatProvider>{element}</BidirectionalCompatProvider>;\n}\n","/*\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 { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\n/**\n * Catch-all type for route params.\n *\n * @public\n */\nexport type AnyRouteRefParams = { [param in string]: string } | undefined;\n\n/**\n * @deprecated use {@link AnyRouteRefParams} instead\n * @public\n */\nexport type AnyParams = AnyRouteRefParams;\n\n/**\n * Type describing the key type of a route parameter mapping.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type ParamKeys<Params extends AnyParams> = keyof Params extends never\n ? []\n : (keyof Params)[];\n\n/**\n * Optional route params.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type OptionalParams<Params extends { [param in string]: string }> =\n Params[keyof Params] extends never ? undefined : Params;\n\n/**\n * TS magic for handling route parameters.\n *\n * @remarks\n *\n * The extra TS magic here is to require a single params argument if the RouteRef\n * had at least one param defined, but require 0 arguments if there are no params defined.\n * Without this we'd have to pass in empty object to all parameter-less RouteRefs\n * just to make TypeScript happy, or we would have to make the argument optional in\n * which case you might forget to pass it in when it is actually required.\n *\n * @public\n */\nexport type RouteFunc<Params extends AnyParams> = (\n ...[params]: Params extends undefined ? readonly [] : readonly [Params]\n) => string;\n\n/**\n * This symbol is what we use at runtime to determine whether a given object\n * is a type of RouteRef or not. It doesn't work well in TypeScript though since\n * the `unique symbol` will refer to different values between package versions.\n * For that reason we use the marker $$routeRefType to represent the symbol at\n * compile-time instead of using the symbol directly.\n *\n * @internal\n */\nexport const routeRefType: unique symbol = getOrCreateGlobalSingleton<any>(\n 'route-ref-type',\n () => Symbol('route-ref-type'),\n);\n\n/**\n * Absolute route reference.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type RouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'absolute'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Descriptor of a route relative to an absolute {@link RouteRef}.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type SubRouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'sub'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n parent: RouteRef;\n\n path: string;\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type ExternalRouteRef<\n Params extends AnyParams = any,\n Optional extends boolean = any,\n> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'external'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n\n optional?: Optional;\n};\n\n/**\n * @internal\n */\nexport type AnyRouteRef =\n | RouteRef<any>\n | SubRouteRef<any>\n | ExternalRouteRef<any, any>;\n\n/**\n * A duplicate of the react-router RouteObject, but with routeRef added\n * @internal\n */\nexport interface BackstageRouteObject {\n caseSensitive: boolean;\n children?: BackstageRouteObject[];\n element: React.ReactNode;\n path: string;\n routeRefs: Set<RouteRef>;\n}\n","/*\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 { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * Absolute route reference.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface RouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/RouteRef';\n readonly T: TParams;\n}\n\n/** @internal */\nexport interface InternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends RouteRef<TParams> {\n readonly version: 'v1';\n getParams(): string[];\n getDescription(): string;\n\n setId(id: string): void;\n}\n\n/** @internal */\nexport function toInternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: RouteRef<TParams>): InternalRouteRef<TParams> {\n const r = resource as InternalRouteRef<TParams>;\n if (r.$$type !== '@backstage/RouteRef') {\n throw new Error(`Invalid RouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isRouteRef(opaque: { $$type: string }): opaque is RouteRef {\n return opaque.$$type === '@backstage/RouteRef';\n}\n\n/** @internal */\nexport class RouteRefImpl implements InternalRouteRef {\n readonly $$type = '@backstage/RouteRef';\n readonly version = 'v1';\n declare readonly T: never;\n\n #id?: string;\n #params: string[];\n #creationSite: string;\n\n constructor(readonly params: string[] = [], creationSite: string) {\n this.#params = params;\n this.#creationSite = creationSite;\n }\n\n getParams(): string[] {\n return this.#params;\n }\n\n getDescription(): string {\n if (this.#id) {\n return this.#id;\n }\n return `created at '${this.#creationSite}'`;\n }\n\n get #name() {\n return this.$$type.slice('@backstage/'.length);\n }\n\n setId(id: string): void {\n if (!id) {\n throw new Error(`${this.#name} id must be a non-empty string`);\n }\n if (this.#id) {\n throw new Error(\n `${this.#name} was referenced twice as both '${this.#id}' and '${id}'`,\n );\n }\n this.#id = id;\n }\n\n toString(): string {\n return `${this.#name}{${this.getDescription()}}`;\n }\n}\n\n/**\n * Create a {@link RouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createRouteRef<\n // Params is the type that we care about and the one to be embedded in the route ref.\n // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string}\n TParams extends { [param in TParamKeys]: string } | undefined = undefined,\n TParamKeys extends string = string,\n>(config?: {\n /** A list of parameter names that the path that this route ref is bound to must contain */\n readonly params: string extends TParamKeys ? (keyof TParams)[] : TParamKeys[];\n}): RouteRef<\n keyof TParams extends never\n ? undefined\n : string extends TParamKeys\n ? TParams\n : { [param in TParamKeys]: string }\n> {\n return new RouteRefImpl(\n config?.params as string[] | undefined,\n describeParentCallSite(),\n ) as RouteRef<any>;\n}\n","/*\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 { RouteRef, toInternalRouteRef } from './RouteRef';\nimport { AnyRouteRefParams } from './types';\n\n// Should match the pattern in react-router\nconst PARAM_PATTERN = /^\\w+$/;\n\n/**\n * Descriptor of a route relative to an absolute {@link RouteRef}.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface SubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/SubRouteRef';\n\n readonly T: TParams;\n\n readonly path: string;\n}\n\n/** @internal */\nexport interface InternalSubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends SubRouteRef<TParams> {\n readonly version: 'v1';\n\n getParams(): string[];\n getParent(): RouteRef;\n getDescription(): string;\n}\n\n/** @internal */\nexport function toInternalSubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: SubRouteRef<TParams>): InternalSubRouteRef<TParams> {\n const r = resource as InternalSubRouteRef<TParams>;\n if (r.$$type !== '@backstage/SubRouteRef') {\n throw new Error(`Invalid SubRouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isSubRouteRef(opaque: {\n $$type: string;\n}): opaque is SubRouteRef {\n return opaque.$$type === '@backstage/SubRouteRef';\n}\n\n/** @internal */\nexport class SubRouteRefImpl<TParams extends AnyRouteRefParams>\n implements SubRouteRef<TParams>\n{\n readonly $$type = '@backstage/SubRouteRef';\n readonly version = 'v1';\n declare readonly T: never;\n\n #params: string[];\n #parent: RouteRef;\n\n constructor(readonly path: string, params: string[], parent: RouteRef) {\n this.#params = params;\n this.#parent = parent;\n }\n\n getParams(): string[] {\n return this.#params;\n }\n\n getParent(): RouteRef {\n return this.#parent;\n }\n\n getDescription(): string {\n const parent = toInternalRouteRef(this.#parent);\n return `at ${this.path} with parent ${parent.getDescription()}`;\n }\n\n toString(): string {\n return `SubRouteRef{${this.getDescription()}}`;\n }\n}\n\n/**\n * Used in {@link PathParams} type declaration.\n * @ignore\n */\ntype ParamPart<S extends string> = S extends `:${infer Param}` ? Param : never;\n\n/**\n * Used in {@link PathParams} type declaration.\n * @ignore\n */\ntype ParamNames<S extends string> = S extends `${infer Part}/${infer Rest}`\n ? ParamPart<Part> | ParamNames<Rest>\n : ParamPart<S>;\n/**\n * This utility type helps us infer a Param object type from a string path\n * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }`\n * @ignore\n */\ntype PathParams<S extends string> = { [name in ParamNames<S>]: string };\n\n/**\n * Merges a param object type with an optional params type into a params object.\n * @ignore\n */\ntype MergeParams<\n P1 extends { [param in string]: string },\n P2 extends AnyRouteRefParams,\n> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2);\n\n/**\n * Convert empty params to undefined.\n * @ignore\n */\ntype TrimEmptyParams<Params extends { [param in string]: string }> =\n keyof Params extends never ? undefined : Params;\n\n/**\n * Creates a SubRouteRef type given the desired parameters and parent route parameters.\n * The parameters types are merged together while ensuring that there is no overlap between the two.\n *\n * @ignore\n */\ntype MakeSubRouteRef<\n Params extends { [param in string]: string },\n ParentParams extends AnyRouteRefParams,\n> = keyof Params & keyof ParentParams extends never\n ? SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>>\n : never;\n\n/**\n * Create a {@link SubRouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createSubRouteRef<\n Path extends string,\n ParentParams extends AnyRouteRefParams = never,\n>(config: {\n path: Path;\n parent: RouteRef<ParentParams>;\n}): MakeSubRouteRef<PathParams<Path>, ParentParams> {\n const { path, parent } = config;\n type Params = PathParams<Path>;\n\n const internalParent = toInternalRouteRef(parent);\n const parentParams = internalParent.getParams();\n\n // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz'\n const pathParams = path\n .split('/')\n .filter(p => p.startsWith(':'))\n .map(p => p.substring(1));\n const params = [...parentParams, ...pathParams];\n\n if (parentParams.some(p => pathParams.includes(p as string))) {\n throw new Error(\n 'SubRouteRef may not have params that overlap with its parent',\n );\n }\n if (!path.startsWith('/')) {\n throw new Error(`SubRouteRef path must start with '/', got '${path}'`);\n }\n if (path.endsWith('/')) {\n throw new Error(`SubRouteRef path must not end with '/', got '${path}'`);\n }\n for (const param of pathParams) {\n if (!PARAM_PATTERN.test(param)) {\n throw new Error(`SubRouteRef path has invalid param, got '${param}'`);\n }\n }\n\n // We ensure that the type of the return type is sane here\n const subRouteRef = new SubRouteRefImpl(\n path,\n params as string[],\n parent,\n ) as SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>>;\n\n // But skip type checking of the return value itself, because the conditional\n // type checking of the parent parameter overlap is tricky to express.\n return subRouteRef as any;\n}\n","/*\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 { RouteRefImpl } from './RouteRef';\nimport { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface ExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n TOptional extends boolean = boolean,\n> {\n readonly $$type: '@backstage/ExternalRouteRef';\n readonly T: TParams;\n readonly optional: TOptional;\n}\n\n/** @internal */\nexport interface InternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n TOptional extends boolean = boolean,\n> extends ExternalRouteRef<TParams, TOptional> {\n readonly version: 'v1';\n getParams(): string[];\n getDescription(): string;\n\n setId(id: string): void;\n}\n\n/** @internal */\nexport function toInternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n TOptional extends boolean = boolean,\n>(\n resource: ExternalRouteRef<TParams, TOptional>,\n): InternalExternalRouteRef<TParams, TOptional> {\n const r = resource as InternalExternalRouteRef<TParams, TOptional>;\n if (r.$$type !== '@backstage/ExternalRouteRef') {\n throw new Error(`Invalid ExternalRouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isExternalRouteRef(opaque: {\n $$type: string;\n}): opaque is ExternalRouteRef {\n return opaque.$$type === '@backstage/ExternalRouteRef';\n}\n\n/** @internal */\nclass ExternalRouteRefImpl\n extends RouteRefImpl\n implements InternalExternalRouteRef\n{\n readonly $$type = '@backstage/ExternalRouteRef' as any;\n\n constructor(\n readonly optional: boolean,\n readonly params: string[] = [],\n creationSite: string,\n ) {\n super(params, creationSite);\n }\n}\n\n/**\n * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @param options - Description of the route reference to be created.\n * @public\n */\nexport function createExternalRouteRef<\n TParams extends { [param in TParamKeys]: string } | undefined = undefined,\n TOptional extends boolean = false,\n TParamKeys extends string = string,\n>(options?: {\n /**\n * The parameters that will be provided to the external route reference.\n */\n readonly params?: string extends TParamKeys\n ? (keyof TParams)[]\n : TParamKeys[];\n\n /**\n * Whether or not this route is optional, defaults to false.\n *\n * Optional external routes are not required to be bound in the app, and\n * if they aren't, `useExternalRouteRef` will return `undefined`.\n */\n optional?: TOptional;\n}): ExternalRouteRef<\n keyof TParams extends never\n ? undefined\n : string extends TParamKeys\n ? TParams\n : { [param in TParamKeys]: string },\n TOptional\n> {\n return new ExternalRouteRefImpl(\n Boolean(options?.optional),\n options?.params as string[] | undefined,\n describeParentCallSite(),\n ) as ExternalRouteRef<any, any>;\n}\n","/*\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 RouteRef as LegacyRouteRef,\n SubRouteRef as LegacySubRouteRef,\n ExternalRouteRef as LegacyExternalRouteRef,\n AnyRouteRefParams,\n} from '@backstage/core-plugin-api';\n\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { routeRefType } from '../../core-plugin-api/src/routing/types';\n\nimport {\n RouteRef,\n SubRouteRef,\n ExternalRouteRef,\n createRouteRef,\n createSubRouteRef,\n createExternalRouteRef,\n} from '@backstage/frontend-plugin-api';\n\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalRouteRef } from '../../frontend-plugin-api/src/routing/RouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalSubRouteRef } from '../../frontend-plugin-api/src/routing/SubRouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExternalRouteRef } from '../../frontend-plugin-api/src/routing/ExternalRouteRef';\n\n/**\n * A temporary helper to convert a legacy route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacyRouteRef<TParams>,\n): RouteRef<TParams>;\n\n/**\n * A temporary helper to convert a legacy sub route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createSubRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacySubRouteRef<TParams>,\n): SubRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a legacy external route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createExternalRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<\n TParams extends AnyRouteRefParams,\n TOptional extends boolean,\n>(\n ref: LegacyExternalRouteRef<TParams, TOptional>,\n): ExternalRouteRef<TParams, TOptional>;\n\nexport function convertLegacyRouteRef(\n ref: LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef,\n): RouteRef | SubRouteRef | ExternalRouteRef {\n // Ref has already been converted\n if ('$$type' in ref) {\n return ref as unknown as RouteRef | SubRouteRef | ExternalRouteRef;\n }\n\n const type = (ref as unknown as { [routeRefType]: unknown })[routeRefType];\n\n if (type === 'absolute') {\n const legacyRef = ref as LegacyRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalRouteRef(\n createRouteRef<{ [key in string]: string }>({\n params: legacyRef.params as string[],\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/RouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getDescription() {\n return legacyRefStr;\n },\n setId(id: string) {\n newRef.setId(id);\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n if (type === 'sub') {\n const legacyRef = ref as LegacySubRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalSubRouteRef(\n createSubRouteRef({\n path: legacyRef.path,\n parent: convertLegacyRouteRef(legacyRef.parent),\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/SubRouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getParent() {\n return newRef.getParent();\n },\n getDescription() {\n return legacyRefStr;\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n if (type === 'external') {\n const legacyRef = ref as LegacyExternalRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalExternalRouteRef(\n createExternalRouteRef<{ [key in string]: string }>({\n params: legacyRef.params as string[],\n optional: legacyRef.optional,\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/ExternalRouteRef' as const,\n version: 'v1',\n T: newRef.T,\n optional: newRef.optional,\n getParams() {\n return newRef.getParams();\n },\n getDescription() {\n return legacyRefStr;\n },\n setId(id: string) {\n newRef.setId(id);\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n\n throw new Error(`Failed to convert legacy route ref, unknown type '${type}'`);\n}\n","/*\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 AnyRouteRefParams,\n BackstagePlugin as LegacyBackstagePlugin,\n RouteRef,\n getComponentData,\n} from '@backstage/core-plugin-api';\nimport {\n BackstagePlugin,\n ExtensionDefinition,\n coreExtensionData,\n createApiExtension,\n createExtension,\n createExtensionInput,\n createPageExtension,\n createPlugin,\n} from '@backstage/frontend-plugin-api';\nimport React, { Children, ReactNode, isValidElement } from 'react';\nimport { Route, Routes } from 'react-router-dom';\nimport { convertLegacyRouteRef } from './convertLegacyRouteRef';\nimport { compatWrapper } from './compatWrapper';\n\n/*\n\n# Legacy interoperability\n\nUse-cases (prioritized):\n 1. Slowly migrate over an existing app to DI, piece by piece\n 2. Use a legacy plugin in a new DI app\n 3. Use DI in an existing legacy app\n\nStarting point: use-case #1\n\nPotential solutions:\n 1. Codemods (we're not considering this for now)\n 2. Legacy apps are migrated bottom-up, i.e. keep legacy root, replace pages with DI\n 3. Legacy apps are migrated top-down i.e. switch out base to DI, legacy adapter allows for usage of existing app structure\n\nChosen path: #3\n\nExisting tasks:\n - Adopters can migrate their existing app gradually (~4)\n - Example-app uses legacy base with DI adapters\n - Create an API that lets you inject DI into existing apps - working assumption is that this is enough\n - Adopters can use legacy plugins in DI through adapters (~8)\n - App-next uses DI base with legacy adapters\n - Create a legacy adapter that is able to take an existing extension tree\n\n*/\n\n// Creates a shim extension whose purpose is to build up the tree (anchored at\n// the root page) of paths/routeRefs so that the app can bind them properly.\nfunction makeRoutingShimExtension(options: {\n name: string;\n parentExtensionId: string;\n routePath?: string;\n routeRef?: RouteRef;\n}) {\n const { name, parentExtensionId, routePath, routeRef } = options;\n return createExtension({\n kind: 'routing-shim',\n name,\n attachTo: { id: parentExtensionId, input: 'childRoutingShims' },\n inputs: {\n childRoutingShims: createExtensionInput({\n routePath: coreExtensionData.routePath.optional(),\n routeRef: coreExtensionData.routeRef.optional(),\n }),\n },\n output: {\n routePath: coreExtensionData.routePath.optional(),\n routeRef: coreExtensionData.routeRef.optional(),\n },\n factory: () => ({\n routePath,\n routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined,\n }),\n });\n}\n\nfunction visitRouteChildren(options: {\n children: ReactNode;\n parentExtensionId: string;\n context: {\n pluginId: string;\n extensions: ExtensionDefinition<unknown>[];\n getUniqueName: () => string;\n discoverPlugin: (plugin: LegacyBackstagePlugin) => void;\n };\n}): void {\n const { children, parentExtensionId, context } = options;\n const { pluginId, extensions, getUniqueName, discoverPlugin } = context;\n\n Children.forEach(children, node => {\n if (!isValidElement(node)) {\n return;\n }\n\n const plugin = getComponentData<LegacyBackstagePlugin>(node, 'core.plugin');\n const routeRef = getComponentData<RouteRef<AnyRouteRefParams>>(\n node,\n 'core.mountPoint',\n );\n const routePath: string | undefined = node.props?.path;\n\n if (plugin) {\n // We just mark the plugin as discovered, but don't change the context\n discoverPlugin(plugin);\n }\n\n let nextParentExtensionId = parentExtensionId;\n if (routeRef || routePath) {\n const nextParentExtensionName = getUniqueName();\n nextParentExtensionId = `routing-shim:${pluginId}/${nextParentExtensionName}`;\n extensions.push(\n makeRoutingShimExtension({\n name: nextParentExtensionName,\n parentExtensionId,\n routePath,\n routeRef,\n }),\n );\n }\n\n visitRouteChildren({\n children: node.props.children,\n parentExtensionId: nextParentExtensionId,\n context,\n });\n });\n}\n\n/** @internal */\nexport function collectLegacyRoutes(\n flatRoutesElement: JSX.Element,\n): BackstagePlugin[] {\n const pluginExtensions = new Map<\n LegacyBackstagePlugin,\n ExtensionDefinition<unknown>[]\n >();\n\n const getUniqueName = (() => {\n let currentIndex = 1;\n return () => String(currentIndex++);\n })();\n\n const getPluginExtensions = (plugin: LegacyBackstagePlugin) => {\n let extensions = pluginExtensions.get(plugin);\n if (!extensions) {\n extensions = [];\n pluginExtensions.set(plugin, extensions);\n }\n return extensions;\n };\n\n React.Children.forEach(\n flatRoutesElement.props.children,\n (route: ReactNode) => {\n // TODO(freben): Handle feature flag and permissions framework wrapper elements\n if (!React.isValidElement(route) || route.type !== Route) {\n return;\n }\n\n const routeElement = route.props.element;\n const path: string | undefined = route.props.path;\n const plugin = getComponentData<LegacyBackstagePlugin>(\n routeElement,\n 'core.plugin',\n );\n const routeRef = getComponentData<RouteRef>(\n routeElement,\n 'core.mountPoint',\n );\n if (!plugin || !path) {\n return;\n }\n\n const extensions = getPluginExtensions(plugin);\n const pageExtensionName = extensions.length ? getUniqueName() : undefined;\n const pageExtensionId = `page:${plugin.getId()}${\n pageExtensionName ? `/${pageExtensionName}` : pageExtensionName\n }`;\n\n extensions.push(\n createPageExtension({\n name: pageExtensionName,\n defaultPath: path[0] === '/' ? path.slice(1) : path,\n routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined,\n inputs: {\n childRoutingShims: createExtensionInput({\n routePath: coreExtensionData.routePath.optional(),\n routeRef: coreExtensionData.routeRef.optional(),\n }),\n },\n loader: async () =>\n compatWrapper(\n route.props.children ? (\n <Routes>\n <Route path=\"*\" element={routeElement}>\n <Route path=\"*\" element={route.props.children} />\n </Route>\n </Routes>\n ) : (\n routeElement\n ),\n ),\n }),\n );\n\n visitRouteChildren({\n children: route.props.children,\n parentExtensionId: pageExtensionId,\n context: {\n pluginId: plugin.getId(),\n extensions,\n getUniqueName,\n discoverPlugin: getPluginExtensions,\n },\n });\n },\n );\n\n return Array.from(pluginExtensions).map(([plugin, extensions]) =>\n createPlugin({\n id: plugin.getId(),\n extensions: [\n ...extensions,\n ...Array.from(plugin.getApis()).map(factory =>\n createApiExtension({ factory }),\n ),\n ],\n }),\n );\n}\n","/*\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 React, {\n Children,\n Fragment,\n ReactElement,\n ReactNode,\n isValidElement,\n} from 'react';\nimport {\n FrontendFeature,\n coreExtensionData,\n createExtension,\n createExtensionInput,\n createExtensionOverrides,\n} from '@backstage/frontend-plugin-api';\nimport { getComponentData } from '@backstage/core-plugin-api';\nimport { collectLegacyRoutes } from './collectLegacyRoutes';\n\nfunction selectChildren(\n rootNode: ReactNode,\n selector?: (element: ReactElement<{ children?: ReactNode }>) => boolean,\n strictError?: string,\n): Array<ReactElement<{ children?: ReactNode }>> {\n return Children.toArray(rootNode).flatMap(node => {\n if (!isValidElement<{ children?: ReactNode }>(node)) {\n return [];\n }\n\n if (node.type === Fragment) {\n return selectChildren(node.props.children, selector, strictError);\n }\n\n if (selector === undefined || selector(node)) {\n return [node];\n }\n\n if (strictError) {\n throw new Error(strictError);\n }\n\n return selectChildren(node.props.children, selector, strictError);\n });\n}\n\n/** @public */\nexport function convertLegacyApp(\n rootElement: React.JSX.Element,\n): FrontendFeature[] {\n if (getComponentData(rootElement, 'core.type') === 'FlatRoutes') {\n return collectLegacyRoutes(rootElement);\n }\n\n const appRouterEls = selectChildren(\n rootElement,\n el => getComponentData(el, 'core.type') === 'AppRouter',\n );\n if (appRouterEls.length !== 1) {\n throw new Error(\n \"Failed to convert legacy app, AppRouter element could not been found. Make sure it's at the top level of the App element tree\",\n );\n }\n\n const rootEls = selectChildren(\n appRouterEls[0].props.children,\n el =>\n Boolean(el.props.children) &&\n selectChildren(\n el.props.children,\n innerEl => getComponentData(innerEl, 'core.type') === 'FlatRoutes',\n ).length === 1,\n );\n if (rootEls.length !== 1) {\n throw new Error(\n \"Failed to convert legacy app, Root element containing FlatRoutes could not been found. Make sure it's within the AppRouter element of the App element tree\",\n );\n }\n const [rootEl] = rootEls;\n\n const routesEls = selectChildren(\n rootEls[0].props.children,\n el => getComponentData(el, 'core.type') === 'FlatRoutes',\n );\n if (routesEls.length !== 1) {\n throw new Error(\n 'Unexpectedly failed to find FlatRoutes in app element tree',\n );\n }\n const [routesEl] = routesEls;\n\n const CoreLayoutOverride = createExtension({\n namespace: 'app',\n name: 'layout',\n attachTo: { id: 'app', input: 'root' },\n inputs: {\n content: createExtensionInput(\n {\n element: coreExtensionData.reactElement,\n },\n { singleton: true },\n ),\n },\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ inputs }) {\n // Clone the root element, this replaces the FlatRoutes declared in the app with out content input\n return {\n element: React.cloneElement(\n rootEl,\n undefined,\n inputs.content.output.element,\n ),\n };\n },\n });\n const CoreNavOverride = createExtension({\n namespace: 'app',\n name: 'nav',\n attachTo: { id: 'app/layout', input: 'nav' },\n output: {},\n factory: () => ({}),\n disabled: true,\n });\n\n const collectedRoutes = collectLegacyRoutes(routesEl);\n\n return [\n ...collectedRoutes,\n createExtensionOverrides({\n extensions: [CoreLayoutOverride, CoreNavOverride],\n }),\n ];\n}\n"],"names":["createNewPlugin"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../core-app-api/src/app/AppContext.tsx","../src/compatWrapper/BackwardsCompatProvider.tsx","../src/compatWrapper/ForwardsCompatProvider.tsx","../src/compatWrapper/compatWrapper.tsx","../../core-plugin-api/src/routing/types.ts","../../frontend-plugin-api/src/routing/RouteRef.ts","../../frontend-plugin-api/src/routing/SubRouteRef.ts","../../frontend-plugin-api/src/routing/ExternalRouteRef.ts","../src/convertLegacyRouteRef.ts","../src/collectLegacyRoutes.tsx","../src/convertLegacyApp.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 React, { PropsWithChildren } from 'react';\nimport {\n createVersionedValueMap,\n createVersionedContext,\n} from '@backstage/version-bridge';\nimport { AppContext as AppContextV1 } from './types';\n\nconst AppContext = createVersionedContext<{ 1: AppContextV1 }>('app-context');\n\ntype Props = {\n appContext: AppContextV1;\n};\n\nexport const AppContextProvider = ({\n appContext,\n children,\n}: PropsWithChildren<Props>) => {\n const versionedValue = createVersionedValueMap({ 1: appContext });\n\n return <AppContext.Provider value={versionedValue} children={children} />;\n};\n","/*\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 React, { useMemo } from 'react';\nimport { ReactNode } from 'react';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppContextProvider } from '../../../core-app-api/src/app/AppContext';\nimport {\n createPlugin as createNewPlugin,\n BackstagePlugin as NewBackstagePlugin,\n appTreeApiRef,\n componentsApiRef,\n coreComponentRefs,\n iconsApiRef,\n useApi,\n} from '@backstage/frontend-plugin-api';\nimport {\n AppComponents,\n IconComponent,\n BackstagePlugin as LegacyBackstagePlugin,\n} from '@backstage/core-plugin-api';\nimport { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\n// Make sure that we only convert each new plugin instance to its legacy equivalent once\nconst legacyPluginStore = getOrCreateGlobalSingleton(\n 'legacy-plugin-compatibility-store',\n () => new WeakMap<NewBackstagePlugin, LegacyBackstagePlugin>(),\n);\n\nfunction toLegacyPlugin(plugin: NewBackstagePlugin): LegacyBackstagePlugin {\n let legacy = legacyPluginStore.get(plugin);\n if (legacy) {\n return legacy;\n }\n\n const errorMsg = 'Not implemented in legacy plugin compatibility layer';\n const notImplemented = () => {\n throw new Error(errorMsg);\n };\n\n legacy = {\n getId(): string {\n return plugin.id;\n },\n get routes() {\n return {};\n },\n get externalRoutes() {\n return {};\n },\n getApis: notImplemented,\n getFeatureFlags: notImplemented,\n provide: notImplemented,\n };\n\n legacyPluginStore.set(plugin, legacy);\n return legacy;\n}\n\n// TODO: Currently a very naive implementation, may need some more work\nfunction toNewPlugin(plugin: LegacyBackstagePlugin): NewBackstagePlugin {\n return createNewPlugin({\n id: plugin.getId(),\n });\n}\n\n// Recreates the old AppContext APIs using the various new APIs that replaced it\nfunction LegacyAppContextProvider(props: { children: ReactNode }) {\n const appTreeApi = useApi(appTreeApiRef);\n const componentsApi = useApi(componentsApiRef);\n const iconsApi = useApi(iconsApiRef);\n\n const appContext = useMemo(() => {\n const { tree } = appTreeApi.getTree();\n\n let gatheredPlugins: LegacyBackstagePlugin[] | undefined = undefined;\n\n const ErrorBoundaryFallback = componentsApi.getComponent(\n coreComponentRefs.errorBoundaryFallback,\n );\n const ErrorBoundaryFallbackWrapper: AppComponents['ErrorBoundaryFallback'] =\n ({ plugin, ...rest }) => (\n <ErrorBoundaryFallback\n {...rest}\n plugin={plugin && toNewPlugin(plugin)}\n />\n );\n\n return {\n getPlugins(): LegacyBackstagePlugin[] {\n if (gatheredPlugins) {\n return gatheredPlugins;\n }\n\n const pluginSet = new Set<LegacyBackstagePlugin>();\n for (const node of tree.nodes.values()) {\n const plugin = node.spec.source;\n if (plugin) {\n pluginSet.add(toLegacyPlugin(plugin));\n }\n }\n gatheredPlugins = Array.from(pluginSet);\n\n return gatheredPlugins;\n },\n\n getSystemIcon(key: string): IconComponent | undefined {\n return iconsApi.getIcon(key);\n },\n\n getSystemIcons(): Record<string, IconComponent> {\n return Object.fromEntries(\n iconsApi.listIconKeys().map(key => [key, iconsApi.getIcon(key)!]),\n );\n },\n\n getComponents(): AppComponents {\n return {\n NotFoundErrorPage: componentsApi.getComponent(\n coreComponentRefs.notFoundErrorPage,\n ),\n BootErrorPage() {\n throw new Error(\n 'The BootErrorPage app component should not be accessed by plugins',\n );\n },\n Progress: componentsApi.getComponent(coreComponentRefs.progress),\n Router() {\n throw new Error(\n 'The Router app component should not be accessed by plugins',\n );\n },\n ErrorBoundaryFallback: ErrorBoundaryFallbackWrapper,\n };\n },\n };\n }, [appTreeApi, componentsApi, iconsApi]);\n\n return (\n <AppContextProvider appContext={appContext}>\n {props.children}\n </AppContextProvider>\n );\n}\n\nexport function BackwardsCompatProvider(props: { children: ReactNode }) {\n return <LegacyAppContextProvider>{props.children}</LegacyAppContextProvider>;\n}\n","/*\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 React from 'react';\nimport { ReactNode } from 'react';\n\nexport function ForwardsCompatProvider(props: { children: ReactNode }) {\n // TODO(Rugvip): Implement\n return <>{props.children}</>;\n}\n","/*\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 React from 'react';\nimport { useVersionedContext } from '@backstage/version-bridge';\nimport { ReactNode } from 'react';\nimport { BackwardsCompatProvider } from './BackwardsCompatProvider';\nimport { ForwardsCompatProvider } from './ForwardsCompatProvider';\n\nfunction BidirectionalCompatProvider(props: { children: ReactNode }) {\n const isInNewApp = !useVersionedContext<{ 1: unknown }>('app-context');\n\n if (isInNewApp) {\n return <BackwardsCompatProvider {...props} />;\n }\n\n return <ForwardsCompatProvider {...props} />;\n}\n\n/**\n * Wraps a React element in a bidirectional compatibility provider, allow APIs\n * from `@backstage/core-plugin-api` to be used in an app from `@backstage/frontend-app-api`,\n * and APIs from `@backstage/frontend-plugin-api` to be used in an app from `@backstage/core-app-api`.\n *\n * @public\n */\nexport function compatWrapper(element: ReactNode) {\n return <BidirectionalCompatProvider>{element}</BidirectionalCompatProvider>;\n}\n","/*\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 { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\n\n/**\n * Catch-all type for route params.\n *\n * @public\n */\nexport type AnyRouteRefParams = { [param in string]: string } | undefined;\n\n/**\n * @deprecated use {@link AnyRouteRefParams} instead\n * @public\n */\nexport type AnyParams = AnyRouteRefParams;\n\n/**\n * Type describing the key type of a route parameter mapping.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type ParamKeys<Params extends AnyParams> = keyof Params extends never\n ? []\n : (keyof Params)[];\n\n/**\n * Optional route params.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type OptionalParams<Params extends { [param in string]: string }> =\n Params[keyof Params] extends never ? undefined : Params;\n\n/**\n * TS magic for handling route parameters.\n *\n * @remarks\n *\n * The extra TS magic here is to require a single params argument if the RouteRef\n * had at least one param defined, but require 0 arguments if there are no params defined.\n * Without this we'd have to pass in empty object to all parameter-less RouteRefs\n * just to make TypeScript happy, or we would have to make the argument optional in\n * which case you might forget to pass it in when it is actually required.\n *\n * @public\n */\nexport type RouteFunc<Params extends AnyParams> = (\n ...[params]: Params extends undefined ? readonly [] : readonly [Params]\n) => string;\n\n/**\n * This symbol is what we use at runtime to determine whether a given object\n * is a type of RouteRef or not. It doesn't work well in TypeScript though since\n * the `unique symbol` will refer to different values between package versions.\n * For that reason we use the marker $$routeRefType to represent the symbol at\n * compile-time instead of using the symbol directly.\n *\n * @internal\n */\nexport const routeRefType: unique symbol = getOrCreateGlobalSingleton<any>(\n 'route-ref-type',\n () => Symbol('route-ref-type'),\n);\n\n/**\n * Absolute route reference.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type RouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'absolute'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Descriptor of a route relative to an absolute {@link RouteRef}.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type SubRouteRef<Params extends AnyParams = any> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'sub'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n parent: RouteRef;\n\n path: string;\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n};\n\n/**\n * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport type ExternalRouteRef<\n Params extends AnyParams = any,\n Optional extends boolean = any,\n> = {\n /** @deprecated access to this property will be removed in the future */\n $$routeRefType: 'external'; // See routeRefType above\n\n /** @deprecated access to this property will be removed in the future */\n params: ParamKeys<Params>;\n\n optional?: Optional;\n};\n\n/**\n * @internal\n */\nexport type AnyRouteRef =\n | RouteRef<any>\n | SubRouteRef<any>\n | ExternalRouteRef<any, any>;\n\n/**\n * A duplicate of the react-router RouteObject, but with routeRef added\n * @internal\n */\nexport interface BackstageRouteObject {\n caseSensitive: boolean;\n children?: BackstageRouteObject[];\n element: React.ReactNode;\n path: string;\n routeRefs: Set<RouteRef>;\n}\n","/*\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 { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * Absolute route reference.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface RouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/RouteRef';\n readonly T: TParams;\n}\n\n/** @internal */\nexport interface InternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends RouteRef<TParams> {\n readonly version: 'v1';\n getParams(): string[];\n getDescription(): string;\n\n setId(id: string): void;\n}\n\n/** @internal */\nexport function toInternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: RouteRef<TParams>): InternalRouteRef<TParams> {\n const r = resource as InternalRouteRef<TParams>;\n if (r.$$type !== '@backstage/RouteRef') {\n throw new Error(`Invalid RouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isRouteRef(opaque: { $$type: string }): opaque is RouteRef {\n return opaque.$$type === '@backstage/RouteRef';\n}\n\n/** @internal */\nexport class RouteRefImpl implements InternalRouteRef {\n readonly $$type = '@backstage/RouteRef';\n readonly version = 'v1';\n declare readonly T: never;\n\n #id?: string;\n #params: string[];\n #creationSite: string;\n\n constructor(readonly params: string[] = [], creationSite: string) {\n this.#params = params;\n this.#creationSite = creationSite;\n }\n\n getParams(): string[] {\n return this.#params;\n }\n\n getDescription(): string {\n if (this.#id) {\n return this.#id;\n }\n return `created at '${this.#creationSite}'`;\n }\n\n get #name() {\n return this.$$type.slice('@backstage/'.length);\n }\n\n setId(id: string): void {\n if (!id) {\n throw new Error(`${this.#name} id must be a non-empty string`);\n }\n if (this.#id) {\n throw new Error(\n `${this.#name} was referenced twice as both '${this.#id}' and '${id}'`,\n );\n }\n this.#id = id;\n }\n\n toString(): string {\n return `${this.#name}{${this.getDescription()}}`;\n }\n}\n\n/**\n * Create a {@link RouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createRouteRef<\n // Params is the type that we care about and the one to be embedded in the route ref.\n // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string}\n TParams extends { [param in TParamKeys]: string } | undefined = undefined,\n TParamKeys extends string = string,\n>(config?: {\n /** A list of parameter names that the path that this route ref is bound to must contain */\n readonly params: string extends TParamKeys ? (keyof TParams)[] : TParamKeys[];\n}): RouteRef<\n keyof TParams extends never\n ? undefined\n : string extends TParamKeys\n ? TParams\n : { [param in TParamKeys]: string }\n> {\n return new RouteRefImpl(\n config?.params as string[] | undefined,\n describeParentCallSite(),\n ) as RouteRef<any>;\n}\n","/*\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 { RouteRef, toInternalRouteRef } from './RouteRef';\nimport { AnyRouteRefParams } from './types';\n\n// Should match the pattern in react-router\nconst PARAM_PATTERN = /^\\w+$/;\n\n/**\n * Descriptor of a route relative to an absolute {@link RouteRef}.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface SubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/SubRouteRef';\n\n readonly T: TParams;\n\n readonly path: string;\n}\n\n/** @internal */\nexport interface InternalSubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends SubRouteRef<TParams> {\n readonly version: 'v1';\n\n getParams(): string[];\n getParent(): RouteRef;\n getDescription(): string;\n}\n\n/** @internal */\nexport function toInternalSubRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: SubRouteRef<TParams>): InternalSubRouteRef<TParams> {\n const r = resource as InternalSubRouteRef<TParams>;\n if (r.$$type !== '@backstage/SubRouteRef') {\n throw new Error(`Invalid SubRouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isSubRouteRef(opaque: {\n $$type: string;\n}): opaque is SubRouteRef {\n return opaque.$$type === '@backstage/SubRouteRef';\n}\n\n/** @internal */\nexport class SubRouteRefImpl<TParams extends AnyRouteRefParams>\n implements SubRouteRef<TParams>\n{\n readonly $$type = '@backstage/SubRouteRef';\n readonly version = 'v1';\n declare readonly T: never;\n\n #params: string[];\n #parent: RouteRef;\n\n constructor(readonly path: string, params: string[], parent: RouteRef) {\n this.#params = params;\n this.#parent = parent;\n }\n\n getParams(): string[] {\n return this.#params;\n }\n\n getParent(): RouteRef {\n return this.#parent;\n }\n\n getDescription(): string {\n const parent = toInternalRouteRef(this.#parent);\n return `at ${this.path} with parent ${parent.getDescription()}`;\n }\n\n toString(): string {\n return `SubRouteRef{${this.getDescription()}}`;\n }\n}\n\n/**\n * Used in {@link PathParams} type declaration.\n * @ignore\n */\ntype ParamPart<S extends string> = S extends `:${infer Param}` ? Param : never;\n\n/**\n * Used in {@link PathParams} type declaration.\n * @ignore\n */\ntype ParamNames<S extends string> = S extends `${infer Part}/${infer Rest}`\n ? ParamPart<Part> | ParamNames<Rest>\n : ParamPart<S>;\n/**\n * This utility type helps us infer a Param object type from a string path\n * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }`\n * @ignore\n */\ntype PathParams<S extends string> = { [name in ParamNames<S>]: string };\n\n/**\n * Merges a param object type with an optional params type into a params object.\n * @ignore\n */\ntype MergeParams<\n P1 extends { [param in string]: string },\n P2 extends AnyRouteRefParams,\n> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2);\n\n/**\n * Convert empty params to undefined.\n * @ignore\n */\ntype TrimEmptyParams<Params extends { [param in string]: string }> =\n keyof Params extends never ? undefined : Params;\n\n/**\n * Creates a SubRouteRef type given the desired parameters and parent route parameters.\n * The parameters types are merged together while ensuring that there is no overlap between the two.\n *\n * @ignore\n */\ntype MakeSubRouteRef<\n Params extends { [param in string]: string },\n ParentParams extends AnyRouteRefParams,\n> = keyof Params & keyof ParentParams extends never\n ? SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>>\n : never;\n\n/**\n * Create a {@link SubRouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createSubRouteRef<\n Path extends string,\n ParentParams extends AnyRouteRefParams = never,\n>(config: {\n path: Path;\n parent: RouteRef<ParentParams>;\n}): MakeSubRouteRef<PathParams<Path>, ParentParams> {\n const { path, parent } = config;\n type Params = PathParams<Path>;\n\n const internalParent = toInternalRouteRef(parent);\n const parentParams = internalParent.getParams();\n\n // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz'\n const pathParams = path\n .split('/')\n .filter(p => p.startsWith(':'))\n .map(p => p.substring(1));\n const params = [...parentParams, ...pathParams];\n\n if (parentParams.some(p => pathParams.includes(p as string))) {\n throw new Error(\n 'SubRouteRef may not have params that overlap with its parent',\n );\n }\n if (!path.startsWith('/')) {\n throw new Error(`SubRouteRef path must start with '/', got '${path}'`);\n }\n if (path.endsWith('/')) {\n throw new Error(`SubRouteRef path must not end with '/', got '${path}'`);\n }\n for (const param of pathParams) {\n if (!PARAM_PATTERN.test(param)) {\n throw new Error(`SubRouteRef path has invalid param, got '${param}'`);\n }\n }\n\n // We ensure that the type of the return type is sane here\n const subRouteRef = new SubRouteRefImpl(\n path,\n params as string[],\n parent,\n ) as SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>>;\n\n // But skip type checking of the return value itself, because the conditional\n // type checking of the parent parameter overlap is tricky to express.\n return subRouteRef as any;\n}\n","/*\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 { RouteRefImpl } from './RouteRef';\nimport { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @public\n */\nexport interface ExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n TOptional extends boolean = boolean,\n> {\n readonly $$type: '@backstage/ExternalRouteRef';\n readonly T: TParams;\n readonly optional: TOptional;\n}\n\n/** @internal */\nexport interface InternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n TOptional extends boolean = boolean,\n> extends ExternalRouteRef<TParams, TOptional> {\n readonly version: 'v1';\n getParams(): string[];\n getDescription(): string;\n\n setId(id: string): void;\n}\n\n/** @internal */\nexport function toInternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n TOptional extends boolean = boolean,\n>(\n resource: ExternalRouteRef<TParams, TOptional>,\n): InternalExternalRouteRef<TParams, TOptional> {\n const r = resource as InternalExternalRouteRef<TParams, TOptional>;\n if (r.$$type !== '@backstage/ExternalRouteRef') {\n throw new Error(`Invalid ExternalRouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isExternalRouteRef(opaque: {\n $$type: string;\n}): opaque is ExternalRouteRef {\n return opaque.$$type === '@backstage/ExternalRouteRef';\n}\n\n/** @internal */\nclass ExternalRouteRefImpl\n extends RouteRefImpl\n implements InternalExternalRouteRef\n{\n readonly $$type = '@backstage/ExternalRouteRef' as any;\n\n constructor(\n readonly optional: boolean,\n readonly params: string[] = [],\n creationSite: string,\n ) {\n super(params, creationSite);\n }\n}\n\n/**\n * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @param options - Description of the route reference to be created.\n * @public\n */\nexport function createExternalRouteRef<\n TParams extends { [param in TParamKeys]: string } | undefined = undefined,\n TOptional extends boolean = false,\n TParamKeys extends string = string,\n>(options?: {\n /**\n * The parameters that will be provided to the external route reference.\n */\n readonly params?: string extends TParamKeys\n ? (keyof TParams)[]\n : TParamKeys[];\n\n /**\n * Whether or not this route is optional, defaults to false.\n *\n * Optional external routes are not required to be bound in the app, and\n * if they aren't, `useExternalRouteRef` will return `undefined`.\n */\n optional?: TOptional;\n}): ExternalRouteRef<\n keyof TParams extends never\n ? undefined\n : string extends TParamKeys\n ? TParams\n : { [param in TParamKeys]: string },\n TOptional\n> {\n return new ExternalRouteRefImpl(\n Boolean(options?.optional),\n options?.params as string[] | undefined,\n describeParentCallSite(),\n ) as ExternalRouteRef<any, any>;\n}\n","/*\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 RouteRef as LegacyRouteRef,\n SubRouteRef as LegacySubRouteRef,\n ExternalRouteRef as LegacyExternalRouteRef,\n AnyRouteRefParams,\n} from '@backstage/core-plugin-api';\n\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { routeRefType } from '../../core-plugin-api/src/routing/types';\n\nimport {\n RouteRef,\n SubRouteRef,\n ExternalRouteRef,\n createRouteRef,\n createSubRouteRef,\n createExternalRouteRef,\n} from '@backstage/frontend-plugin-api';\n\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalRouteRef } from '../../frontend-plugin-api/src/routing/RouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalSubRouteRef } from '../../frontend-plugin-api/src/routing/SubRouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExternalRouteRef } from '../../frontend-plugin-api/src/routing/ExternalRouteRef';\n\n/**\n * Converts a legacy route ref type to the new system.\n *\n * @public\n */\nexport type ToNewRouteRef<\n T extends LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef,\n> = T extends LegacyRouteRef<infer IParams>\n ? RouteRef<IParams>\n : T extends LegacySubRouteRef<infer IParams>\n ? SubRouteRef<IParams>\n : T extends LegacyExternalRouteRef<infer IParams, infer IOptional>\n ? ExternalRouteRef<IParams, IOptional>\n : never;\n\n/**\n * Converts a collection of legacy route refs to the new system.\n * This is particularly useful when defining plugin `routes` and `externalRoutes`.\n *\n * @public\n */\nexport function convertLegacyRouteRefs<\n TRefs extends {\n [name in string]:\n | LegacyRouteRef\n | LegacySubRouteRef\n | LegacyExternalRouteRef;\n },\n>(refs: TRefs): { [KName in keyof TRefs]: ToNewRouteRef<TRefs[KName]> } {\n return Object.fromEntries(\n Object.entries(refs).map(([name, ref]) => [\n name,\n convertLegacyRouteRef(ref as LegacyRouteRef),\n ]),\n ) as { [KName in keyof TRefs]: ToNewRouteRef<TRefs[KName]> };\n}\n\n/**\n * A temporary helper to convert a legacy route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacyRouteRef<TParams>,\n): RouteRef<TParams>;\n\n/**\n * A temporary helper to convert a legacy sub route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createSubRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<TParams extends AnyRouteRefParams>(\n ref: LegacySubRouteRef<TParams>,\n): SubRouteRef<TParams>;\n\n/**\n * A temporary helper to convert a legacy external route ref to the new system.\n *\n * @public\n * @remarks\n *\n * In the future the legacy createExternalRouteRef will instead create refs compatible with both systems.\n */\nexport function convertLegacyRouteRef<\n TParams extends AnyRouteRefParams,\n TOptional extends boolean,\n>(\n ref: LegacyExternalRouteRef<TParams, TOptional>,\n): ExternalRouteRef<TParams, TOptional>;\n\nexport function convertLegacyRouteRef(\n ref: LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef,\n): RouteRef | SubRouteRef | ExternalRouteRef {\n // Ref has already been converted\n if ('$$type' in ref) {\n return ref as unknown as RouteRef | SubRouteRef | ExternalRouteRef;\n }\n\n const type = (ref as unknown as { [routeRefType]: unknown })[routeRefType];\n\n if (type === 'absolute') {\n const legacyRef = ref as LegacyRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalRouteRef(\n createRouteRef<{ [key in string]: string }>({\n params: legacyRef.params as string[],\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/RouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getDescription() {\n return legacyRefStr;\n },\n setId(id: string) {\n newRef.setId(id);\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n if (type === 'sub') {\n const legacyRef = ref as LegacySubRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalSubRouteRef(\n createSubRouteRef({\n path: legacyRef.path,\n parent: convertLegacyRouteRef(legacyRef.parent),\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/SubRouteRef' as const,\n version: 'v1',\n T: newRef.T,\n getParams() {\n return newRef.getParams();\n },\n getParent() {\n return newRef.getParent();\n },\n getDescription() {\n return legacyRefStr;\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n if (type === 'external') {\n const legacyRef = ref as LegacyExternalRouteRef;\n const legacyRefStr = String(legacyRef);\n const newRef = toInternalExternalRouteRef(\n createExternalRouteRef<{ [key in string]: string }>({\n params: legacyRef.params as string[],\n optional: legacyRef.optional,\n }),\n );\n return Object.assign(legacyRef, {\n $$type: '@backstage/ExternalRouteRef' as const,\n version: 'v1',\n T: newRef.T,\n optional: newRef.optional,\n getParams() {\n return newRef.getParams();\n },\n getDescription() {\n return legacyRefStr;\n },\n setId(id: string) {\n newRef.setId(id);\n },\n toString() {\n return legacyRefStr;\n },\n });\n }\n\n throw new Error(`Failed to convert legacy route ref, unknown type '${type}'`);\n}\n","/*\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 AnyRouteRefParams,\n BackstagePlugin as LegacyBackstagePlugin,\n RouteRef,\n getComponentData,\n} from '@backstage/core-plugin-api';\nimport {\n BackstagePlugin,\n ExtensionDefinition,\n coreExtensionData,\n createApiExtension,\n createExtension,\n createExtensionInput,\n createPageExtension,\n createPlugin,\n} from '@backstage/frontend-plugin-api';\nimport React, { Children, ReactNode, isValidElement } from 'react';\nimport { Route, Routes } from 'react-router-dom';\nimport {\n convertLegacyRouteRef,\n convertLegacyRouteRefs,\n} from './convertLegacyRouteRef';\nimport { compatWrapper } from './compatWrapper';\n\n/*\n\n# Legacy interoperability\n\nUse-cases (prioritized):\n 1. Slowly migrate over an existing app to DI, piece by piece\n 2. Use a legacy plugin in a new DI app\n 3. Use DI in an existing legacy app\n\nStarting point: use-case #1\n\nPotential solutions:\n 1. Codemods (we're not considering this for now)\n 2. Legacy apps are migrated bottom-up, i.e. keep legacy root, replace pages with DI\n 3. Legacy apps are migrated top-down i.e. switch out base to DI, legacy adapter allows for usage of existing app structure\n\nChosen path: #3\n\nExisting tasks:\n - Adopters can migrate their existing app gradually (~4)\n - Example-app uses legacy base with DI adapters\n - Create an API that lets you inject DI into existing apps - working assumption is that this is enough\n - Adopters can use legacy plugins in DI through adapters (~8)\n - App-next uses DI base with legacy adapters\n - Create a legacy adapter that is able to take an existing extension tree\n\n*/\n\n// Creates a shim extension whose purpose is to build up the tree (anchored at\n// the root page) of paths/routeRefs so that the app can bind them properly.\nfunction makeRoutingShimExtension(options: {\n name: string;\n parentExtensionId: string;\n routePath?: string;\n routeRef?: RouteRef;\n}) {\n const { name, parentExtensionId, routePath, routeRef } = options;\n return createExtension({\n kind: 'routing-shim',\n name,\n attachTo: { id: parentExtensionId, input: 'childRoutingShims' },\n inputs: {\n childRoutingShims: createExtensionInput({\n routePath: coreExtensionData.routePath.optional(),\n routeRef: coreExtensionData.routeRef.optional(),\n }),\n },\n output: {\n routePath: coreExtensionData.routePath.optional(),\n routeRef: coreExtensionData.routeRef.optional(),\n },\n factory: () => ({\n routePath,\n routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined,\n }),\n });\n}\n\nfunction visitRouteChildren(options: {\n children: ReactNode;\n parentExtensionId: string;\n context: {\n pluginId: string;\n extensions: ExtensionDefinition<unknown>[];\n getUniqueName: () => string;\n discoverPlugin: (plugin: LegacyBackstagePlugin) => void;\n };\n}): void {\n const { children, parentExtensionId, context } = options;\n const { pluginId, extensions, getUniqueName, discoverPlugin } = context;\n\n Children.forEach(children, node => {\n if (!isValidElement(node)) {\n return;\n }\n\n const plugin = getComponentData<LegacyBackstagePlugin>(node, 'core.plugin');\n const routeRef = getComponentData<RouteRef<AnyRouteRefParams>>(\n node,\n 'core.mountPoint',\n );\n const routePath: string | undefined = node.props?.path;\n\n if (plugin) {\n // We just mark the plugin as discovered, but don't change the context\n discoverPlugin(plugin);\n }\n\n let nextParentExtensionId = parentExtensionId;\n if (routeRef || routePath) {\n const nextParentExtensionName = getUniqueName();\n nextParentExtensionId = `routing-shim:${pluginId}/${nextParentExtensionName}`;\n extensions.push(\n makeRoutingShimExtension({\n name: nextParentExtensionName,\n parentExtensionId,\n routePath,\n routeRef,\n }),\n );\n }\n\n visitRouteChildren({\n children: node.props.children,\n parentExtensionId: nextParentExtensionId,\n context,\n });\n });\n}\n\n/** @internal */\nexport function collectLegacyRoutes(\n flatRoutesElement: JSX.Element,\n): BackstagePlugin[] {\n const pluginExtensions = new Map<\n LegacyBackstagePlugin,\n ExtensionDefinition<unknown>[]\n >();\n\n const getUniqueName = (() => {\n let currentIndex = 1;\n return () => String(currentIndex++);\n })();\n\n const getPluginExtensions = (plugin: LegacyBackstagePlugin) => {\n let extensions = pluginExtensions.get(plugin);\n if (!extensions) {\n extensions = [];\n pluginExtensions.set(plugin, extensions);\n }\n return extensions;\n };\n\n React.Children.forEach(\n flatRoutesElement.props.children,\n (route: ReactNode) => {\n // TODO(freben): Handle feature flag and permissions framework wrapper elements\n if (!React.isValidElement(route) || route.type !== Route) {\n return;\n }\n\n const routeElement = route.props.element;\n const path: string | undefined = route.props.path;\n const plugin = getComponentData<LegacyBackstagePlugin>(\n routeElement,\n 'core.plugin',\n );\n const routeRef = getComponentData<RouteRef>(\n routeElement,\n 'core.mountPoint',\n );\n if (!plugin || !path) {\n return;\n }\n\n const extensions = getPluginExtensions(plugin);\n const pageExtensionName = extensions.length ? getUniqueName() : undefined;\n const pageExtensionId = `page:${plugin.getId()}${\n pageExtensionName ? `/${pageExtensionName}` : pageExtensionName\n }`;\n\n extensions.push(\n createPageExtension({\n name: pageExtensionName,\n defaultPath: path[0] === '/' ? path.slice(1) : path,\n routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined,\n inputs: {\n childRoutingShims: createExtensionInput({\n routePath: coreExtensionData.routePath.optional(),\n routeRef: coreExtensionData.routeRef.optional(),\n }),\n },\n loader: async () =>\n compatWrapper(\n route.props.children ? (\n <Routes>\n <Route path=\"*\" element={routeElement}>\n <Route path=\"*\" element={route.props.children} />\n </Route>\n </Routes>\n ) : (\n routeElement\n ),\n ),\n }),\n );\n\n visitRouteChildren({\n children: route.props.children,\n parentExtensionId: pageExtensionId,\n context: {\n pluginId: plugin.getId(),\n extensions,\n getUniqueName,\n discoverPlugin: getPluginExtensions,\n },\n });\n },\n );\n\n return Array.from(pluginExtensions).map(([plugin, extensions]) =>\n createPlugin({\n id: plugin.getId(),\n extensions: [\n ...extensions,\n ...Array.from(plugin.getApis()).map(factory =>\n createApiExtension({ factory }),\n ),\n ],\n routes: convertLegacyRouteRefs(plugin.routes ?? {}),\n externalRoutes: convertLegacyRouteRefs(plugin.externalRoutes ?? {}),\n }),\n );\n}\n","/*\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 React, {\n Children,\n Fragment,\n ReactElement,\n ReactNode,\n isValidElement,\n} from 'react';\nimport {\n FrontendFeature,\n coreExtensionData,\n createExtension,\n createExtensionInput,\n createExtensionOverrides,\n} from '@backstage/frontend-plugin-api';\nimport { getComponentData } from '@backstage/core-plugin-api';\nimport { collectLegacyRoutes } from './collectLegacyRoutes';\n\nfunction selectChildren(\n rootNode: ReactNode,\n selector?: (element: ReactElement<{ children?: ReactNode }>) => boolean,\n strictError?: string,\n): Array<ReactElement<{ children?: ReactNode }>> {\n return Children.toArray(rootNode).flatMap(node => {\n if (!isValidElement<{ children?: ReactNode }>(node)) {\n return [];\n }\n\n if (node.type === Fragment) {\n return selectChildren(node.props.children, selector, strictError);\n }\n\n if (selector === undefined || selector(node)) {\n return [node];\n }\n\n if (strictError) {\n throw new Error(strictError);\n }\n\n return selectChildren(node.props.children, selector, strictError);\n });\n}\n\n/** @public */\nexport function convertLegacyApp(\n rootElement: React.JSX.Element,\n): FrontendFeature[] {\n if (getComponentData(rootElement, 'core.type') === 'FlatRoutes') {\n return collectLegacyRoutes(rootElement);\n }\n\n const appRouterEls = selectChildren(\n rootElement,\n el => getComponentData(el, 'core.type') === 'AppRouter',\n );\n if (appRouterEls.length !== 1) {\n throw new Error(\n \"Failed to convert legacy app, AppRouter element could not been found. Make sure it's at the top level of the App element tree\",\n );\n }\n\n const rootEls = selectChildren(\n appRouterEls[0].props.children,\n el =>\n Boolean(el.props.children) &&\n selectChildren(\n el.props.children,\n innerEl => getComponentData(innerEl, 'core.type') === 'FlatRoutes',\n ).length === 1,\n );\n if (rootEls.length !== 1) {\n throw new Error(\n \"Failed to convert legacy app, Root element containing FlatRoutes could not been found. Make sure it's within the AppRouter element of the App element tree\",\n );\n }\n const [rootEl] = rootEls;\n\n const routesEls = selectChildren(\n rootEls[0].props.children,\n el => getComponentData(el, 'core.type') === 'FlatRoutes',\n );\n if (routesEls.length !== 1) {\n throw new Error(\n 'Unexpectedly failed to find FlatRoutes in app element tree',\n );\n }\n const [routesEl] = routesEls;\n\n const CoreLayoutOverride = createExtension({\n namespace: 'app',\n name: 'layout',\n attachTo: { id: 'app', input: 'root' },\n inputs: {\n content: createExtensionInput(\n {\n element: coreExtensionData.reactElement,\n },\n { singleton: true },\n ),\n },\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ inputs }) {\n // Clone the root element, this replaces the FlatRoutes declared in the app with out content input\n return {\n element: React.cloneElement(\n rootEl,\n undefined,\n inputs.content.output.element,\n ),\n };\n },\n });\n const CoreNavOverride = createExtension({\n namespace: 'app',\n name: 'nav',\n attachTo: { id: 'app/layout', input: 'nav' },\n output: {},\n factory: () => ({}),\n disabled: true,\n });\n\n const collectedRoutes = collectLegacyRoutes(routesEl);\n\n return [\n ...collectedRoutes,\n createExtensionOverrides({\n extensions: [CoreLayoutOverride, CoreNavOverride],\n }),\n ];\n}\n"],"names":["createNewPlugin"],"mappings":";;;;;;AAuBA,MAAM,UAAA,GAAa,uBAA4C,aAAa,CAAA,CAAA;AAMrE,MAAM,qBAAqB,CAAC;AAAA,EACjC,UAAA;AAAA,EACA,QAAA;AACF,CAAgC,KAAA;AAC9B,EAAA,MAAM,cAAiB,GAAA,uBAAA,CAAwB,EAAE,CAAA,EAAG,YAAY,CAAA,CAAA;AAEhE,EAAA,2CAAQ,UAAW,CAAA,QAAA,EAAX,EAAoB,KAAA,EAAO,gBAAgB,QAAoB,EAAA,CAAA,CAAA;AACzE,CAAA;;ACCA,MAAM,iBAAoB,GAAA,0BAAA;AAAA,EACxB,mCAAA;AAAA,EACA,0BAAU,OAAmD,EAAA;AAC/D,CAAA,CAAA;AAEA,SAAS,eAAe,MAAmD,EAAA;AACzE,EAAI,IAAA,MAAA,GAAS,iBAAkB,CAAA,GAAA,CAAI,MAAM,CAAA,CAAA;AACzC,EAAA,IAAI,MAAQ,EAAA;AACV,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,QAAW,GAAA,sDAAA,CAAA;AACjB,EAAA,MAAM,iBAAiB,MAAM;AAC3B,IAAM,MAAA,IAAI,MAAM,QAAQ,CAAA,CAAA;AAAA,GAC1B,CAAA;AAEA,EAAS,MAAA,GAAA;AAAA,IACP,KAAgB,GAAA;AACd,MAAA,OAAO,MAAO,CAAA,EAAA,CAAA;AAAA,KAChB;AAAA,IACA,IAAI,MAAS,GAAA;AACX,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AAAA,IACA,IAAI,cAAiB,GAAA;AACnB,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AAAA,IACA,OAAS,EAAA,cAAA;AAAA,IACT,eAAiB,EAAA,cAAA;AAAA,IACjB,OAAS,EAAA,cAAA;AAAA,GACX,CAAA;AAEA,EAAkB,iBAAA,CAAA,GAAA,CAAI,QAAQ,MAAM,CAAA,CAAA;AACpC,EAAO,OAAA,MAAA,CAAA;AACT,CAAA;AAGA,SAAS,YAAY,MAAmD,EAAA;AACtE,EAAA,OAAOA,YAAgB,CAAA;AAAA,IACrB,EAAA,EAAI,OAAO,KAAM,EAAA;AAAA,GAClB,CAAA,CAAA;AACH,CAAA;AAGA,SAAS,yBAAyB,KAAgC,EAAA;AAChE,EAAM,MAAA,UAAA,GAAa,OAAO,aAAa,CAAA,CAAA;AACvC,EAAM,MAAA,aAAA,GAAgB,OAAO,gBAAgB,CAAA,CAAA;AAC7C,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA,CAAA;AAEnC,EAAM,MAAA,UAAA,GAAa,QAAQ,MAAM;AAC/B,IAAA,MAAM,EAAE,IAAA,EAAS,GAAA,UAAA,CAAW,OAAQ,EAAA,CAAA;AAEpC,IAAA,IAAI,eAAuD,GAAA,KAAA,CAAA,CAAA;AAE3D,IAAA,MAAM,wBAAwB,aAAc,CAAA,YAAA;AAAA,MAC1C,iBAAkB,CAAA,qBAAA;AAAA,KACpB,CAAA;AACA,IAAA,MAAM,+BACJ,CAAC,EAAE,MAAQ,EAAA,GAAG,MACZ,qBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,qBAAA;AAAA,MAAA;AAAA,QACE,GAAG,IAAA;AAAA,QACJ,MAAA,EAAQ,MAAU,IAAA,WAAA,CAAY,MAAM,CAAA;AAAA,OAAA;AAAA,KACtC,CAAA;AAGJ,IAAO,OAAA;AAAA,MACL,UAAsC,GAAA;AACpC,QAAA,IAAI,eAAiB,EAAA;AACnB,UAAO,OAAA,eAAA,CAAA;AAAA,SACT;AAEA,QAAM,MAAA,SAAA,uBAAgB,GAA2B,EAAA,CAAA;AACjD,QAAA,KAAA,MAAW,IAAQ,IAAA,IAAA,CAAK,KAAM,CAAA,MAAA,EAAU,EAAA;AACtC,UAAM,MAAA,MAAA,GAAS,KAAK,IAAK,CAAA,MAAA,CAAA;AACzB,UAAA,IAAI,MAAQ,EAAA;AACV,YAAU,SAAA,CAAA,GAAA,CAAI,cAAe,CAAA,MAAM,CAAC,CAAA,CAAA;AAAA,WACtC;AAAA,SACF;AACA,QAAkB,eAAA,GAAA,KAAA,CAAM,KAAK,SAAS,CAAA,CAAA;AAEtC,QAAO,OAAA,eAAA,CAAA;AAAA,OACT;AAAA,MAEA,cAAc,GAAwC,EAAA;AACpD,QAAO,OAAA,QAAA,CAAS,QAAQ,GAAG,CAAA,CAAA;AAAA,OAC7B;AAAA,MAEA,cAAgD,GAAA;AAC9C,QAAA,OAAO,MAAO,CAAA,WAAA;AAAA,UACZ,QAAA,CAAS,YAAa,EAAA,CAAE,GAAI,CAAA,CAAA,GAAA,KAAO,CAAC,GAAA,EAAK,QAAS,CAAA,OAAA,CAAQ,GAAG,CAAE,CAAC,CAAA;AAAA,SAClE,CAAA;AAAA,OACF;AAAA,MAEA,aAA+B,GAAA;AAC7B,QAAO,OAAA;AAAA,UACL,mBAAmB,aAAc,CAAA,YAAA;AAAA,YAC/B,iBAAkB,CAAA,iBAAA;AAAA,WACpB;AAAA,UACA,aAAgB,GAAA;AACd,YAAA,MAAM,IAAI,KAAA;AAAA,cACR,mEAAA;AAAA,aACF,CAAA;AAAA,WACF;AAAA,UACA,QAAU,EAAA,aAAA,CAAc,YAAa,CAAA,iBAAA,CAAkB,QAAQ,CAAA;AAAA,UAC/D,MAAS,GAAA;AACP,YAAA,MAAM,IAAI,KAAA;AAAA,cACR,4DAAA;AAAA,aACF,CAAA;AAAA,WACF;AAAA,UACA,qBAAuB,EAAA,4BAAA;AAAA,SACzB,CAAA;AAAA,OACF;AAAA,KACF,CAAA;AAAA,GACC,EAAA,CAAC,UAAY,EAAA,aAAA,EAAe,QAAQ,CAAC,CAAA,CAAA;AAExC,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,kBAAA,EAAA,EAAmB,UACjB,EAAA,EAAA,KAAA,CAAM,QACT,CAAA,CAAA;AAEJ,CAAA;AAEO,SAAS,wBAAwB,KAAgC,EAAA;AACtE,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,wBAA0B,EAAA,IAAA,EAAA,KAAA,CAAM,QAAS,CAAA,CAAA;AACnD;;AC7IO,SAAS,uBAAuB,KAAgC,EAAA;AAErE,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAG,MAAM,QAAS,CAAA,CAAA;AAC3B;;ACAA,SAAS,4BAA4B,KAAgC,EAAA;AACnE,EAAM,MAAA,UAAA,GAAa,CAAC,mBAAA,CAAoC,aAAa,CAAA,CAAA;AAErE,EAAA,IAAI,UAAY,EAAA;AACd,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,uBAAyB,EAAA,EAAA,GAAG,KAAO,EAAA,CAAA,CAAA;AAAA,GAC7C;AAEA,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,sBAAwB,EAAA,EAAA,GAAG,KAAO,EAAA,CAAA,CAAA;AAC5C,CAAA;AASO,SAAS,cAAc,OAAoB,EAAA;AAChD,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,mCAA6B,OAAQ,CAAA,CAAA;AAC/C;;ACmCO,MAAM,YAA8B,GAAA,0BAAA;AAAA,EACzC,gBAAA;AAAA,EACA,MAAM,OAAO,gBAAgB,CAAA;AAC/B,CAAA;;AChCO,SAAS,mBAEd,QAAwD,EAAA;AACxD,EAAA,MAAM,CAAI,GAAA,QAAA,CAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,qBAAuB,EAAA;AACtC,IAAA,MAAM,IAAI,KAAA,CAAM,CAA+B,4BAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GAC5D;AAEA,EAAO,OAAA,CAAA,CAAA;AACT;;ACHO,SAAS,sBAEd,QAA8D,EAAA;AAC9D,EAAA,MAAM,CAAI,GAAA,QAAA,CAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,wBAA0B,EAAA;AACzC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAkC,+BAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GAC/D;AAEA,EAAO,OAAA,CAAA,CAAA;AACT;;ACXO,SAAS,2BAId,QAC8C,EAAA;AAC9C,EAAA,MAAM,CAAI,GAAA,QAAA,CAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,6BAA+B,EAAA;AAC9C,IAAA,MAAM,IAAI,KAAA,CAAM,CAAuC,oCAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GACpE;AAEA,EAAO,OAAA,CAAA,CAAA;AACT;;ACAO,SAAS,uBAOd,IAAsE,EAAA;AACtE,EAAA,OAAO,MAAO,CAAA,WAAA;AAAA,IACZ,MAAA,CAAO,QAAQ,IAAI,CAAA,CAAE,IAAI,CAAC,CAAC,IAAM,EAAA,GAAG,CAAM,KAAA;AAAA,MACxC,IAAA;AAAA,MACA,sBAAsB,GAAqB,CAAA;AAAA,KAC5C,CAAA;AAAA,GACH,CAAA;AACF,CAAA;AAyCO,SAAS,sBACd,GAC2C,EAAA;AAE3C,EAAA,IAAI,YAAY,GAAK,EAAA;AACnB,IAAO,OAAA,GAAA,CAAA;AAAA,GACT;AAEA,EAAM,MAAA,IAAA,GAAQ,IAA+C,YAAY,CAAA,CAAA;AAEzE,EAAA,IAAI,SAAS,UAAY,EAAA;AACvB,IAAA,MAAM,SAAY,GAAA,GAAA,CAAA;AAClB,IAAM,MAAA,YAAA,GAAe,OAAO,SAAS,CAAA,CAAA;AACrC,IAAA,MAAM,MAAS,GAAA,kBAAA;AAAA,MACb,cAA4C,CAAA;AAAA,QAC1C,QAAQ,SAAU,CAAA,MAAA;AAAA,OACnB,CAAA;AAAA,KACH,CAAA;AACA,IAAO,OAAA,MAAA,CAAO,OAAO,SAAW,EAAA;AAAA,MAC9B,MAAQ,EAAA,qBAAA;AAAA,MACR,OAAS,EAAA,IAAA;AAAA,MACT,GAAG,MAAO,CAAA,CAAA;AAAA,MACV,SAAY,GAAA;AACV,QAAA,OAAO,OAAO,SAAU,EAAA,CAAA;AAAA,OAC1B;AAAA,MACA,cAAiB,GAAA;AACf,QAAO,OAAA,YAAA,CAAA;AAAA,OACT;AAAA,MACA,MAAM,EAAY,EAAA;AAChB,QAAA,MAAA,CAAO,MAAM,EAAE,CAAA,CAAA;AAAA,OACjB;AAAA,MACA,QAAW,GAAA;AACT,QAAO,OAAA,YAAA,CAAA;AAAA,OACT;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AACA,EAAA,IAAI,SAAS,KAAO,EAAA;AAClB,IAAA,MAAM,SAAY,GAAA,GAAA,CAAA;AAClB,IAAM,MAAA,YAAA,GAAe,OAAO,SAAS,CAAA,CAAA;AACrC,IAAA,MAAM,MAAS,GAAA,qBAAA;AAAA,MACb,iBAAkB,CAAA;AAAA,QAChB,MAAM,SAAU,CAAA,IAAA;AAAA,QAChB,MAAA,EAAQ,qBAAsB,CAAA,SAAA,CAAU,MAAM,CAAA;AAAA,OAC/C,CAAA;AAAA,KACH,CAAA;AACA,IAAO,OAAA,MAAA,CAAO,OAAO,SAAW,EAAA;AAAA,MAC9B,MAAQ,EAAA,wBAAA;AAAA,MACR,OAAS,EAAA,IAAA;AAAA,MACT,GAAG,MAAO,CAAA,CAAA;AAAA,MACV,SAAY,GAAA;AACV,QAAA,OAAO,OAAO,SAAU,EAAA,CAAA;AAAA,OAC1B;AAAA,MACA,SAAY,GAAA;AACV,QAAA,OAAO,OAAO,SAAU,EAAA,CAAA;AAAA,OAC1B;AAAA,MACA,cAAiB,GAAA;AACf,QAAO,OAAA,YAAA,CAAA;AAAA,OACT;AAAA,MACA,QAAW,GAAA;AACT,QAAO,OAAA,YAAA,CAAA;AAAA,OACT;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AACA,EAAA,IAAI,SAAS,UAAY,EAAA;AACvB,IAAA,MAAM,SAAY,GAAA,GAAA,CAAA;AAClB,IAAM,MAAA,YAAA,GAAe,OAAO,SAAS,CAAA,CAAA;AACrC,IAAA,MAAM,MAAS,GAAA,0BAAA;AAAA,MACb,sBAAoD,CAAA;AAAA,QAClD,QAAQ,SAAU,CAAA,MAAA;AAAA,QAClB,UAAU,SAAU,CAAA,QAAA;AAAA,OACrB,CAAA;AAAA,KACH,CAAA;AACA,IAAO,OAAA,MAAA,CAAO,OAAO,SAAW,EAAA;AAAA,MAC9B,MAAQ,EAAA,6BAAA;AAAA,MACR,OAAS,EAAA,IAAA;AAAA,MACT,GAAG,MAAO,CAAA,CAAA;AAAA,MACV,UAAU,MAAO,CAAA,QAAA;AAAA,MACjB,SAAY,GAAA;AACV,QAAA,OAAO,OAAO,SAAU,EAAA,CAAA;AAAA,OAC1B;AAAA,MACA,cAAiB,GAAA;AACf,QAAO,OAAA,YAAA,CAAA;AAAA,OACT;AAAA,MACA,MAAM,EAAY,EAAA;AAChB,QAAA,MAAA,CAAO,MAAM,EAAE,CAAA,CAAA;AAAA,OACjB;AAAA,MACA,QAAW,GAAA;AACT,QAAO,OAAA,YAAA,CAAA;AAAA,OACT;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AAEA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAqD,kDAAA,EAAA,IAAI,CAAG,CAAA,CAAA,CAAA,CAAA;AAC9E;;AC7IA,SAAS,yBAAyB,OAK/B,EAAA;AACD,EAAA,MAAM,EAAE,IAAA,EAAM,iBAAmB,EAAA,SAAA,EAAW,UAAa,GAAA,OAAA,CAAA;AACzD,EAAA,OAAO,eAAgB,CAAA;AAAA,IACrB,IAAM,EAAA,cAAA;AAAA,IACN,IAAA;AAAA,IACA,QAAU,EAAA,EAAE,EAAI,EAAA,iBAAA,EAAmB,OAAO,mBAAoB,EAAA;AAAA,IAC9D,MAAQ,EAAA;AAAA,MACN,mBAAmB,oBAAqB,CAAA;AAAA,QACtC,SAAA,EAAW,iBAAkB,CAAA,SAAA,CAAU,QAAS,EAAA;AAAA,QAChD,QAAA,EAAU,iBAAkB,CAAA,QAAA,CAAS,QAAS,EAAA;AAAA,OAC/C,CAAA;AAAA,KACH;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,SAAA,EAAW,iBAAkB,CAAA,SAAA,CAAU,QAAS,EAAA;AAAA,MAChD,QAAA,EAAU,iBAAkB,CAAA,QAAA,CAAS,QAAS,EAAA;AAAA,KAChD;AAAA,IACA,SAAS,OAAO;AAAA,MACd,SAAA;AAAA,MACA,QAAU,EAAA,QAAA,GAAW,qBAAsB,CAAA,QAAQ,CAAI,GAAA,KAAA,CAAA;AAAA,KACzD,CAAA;AAAA,GACD,CAAA,CAAA;AACH,CAAA;AAEA,SAAS,mBAAmB,OASnB,EAAA;AACP,EAAA,MAAM,EAAE,QAAA,EAAU,iBAAmB,EAAA,OAAA,EAAY,GAAA,OAAA,CAAA;AACjD,EAAA,MAAM,EAAE,QAAA,EAAU,UAAY,EAAA,aAAA,EAAe,gBAAmB,GAAA,OAAA,CAAA;AAEhE,EAAS,QAAA,CAAA,OAAA,CAAQ,UAAU,CAAQ,IAAA,KAAA;AA/GrC,IAAA,IAAA,EAAA,CAAA;AAgHI,IAAI,IAAA,CAAC,cAAe,CAAA,IAAI,CAAG,EAAA;AACzB,MAAA,OAAA;AAAA,KACF;AAEA,IAAM,MAAA,MAAA,GAAS,gBAAwC,CAAA,IAAA,EAAM,aAAa,CAAA,CAAA;AAC1E,IAAA,MAAM,QAAW,GAAA,gBAAA;AAAA,MACf,IAAA;AAAA,MACA,iBAAA;AAAA,KACF,CAAA;AACA,IAAM,MAAA,SAAA,GAAA,CAAgC,EAAK,GAAA,IAAA,CAAA,KAAA,KAAL,IAAY,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAA,CAAA;AAElD,IAAA,IAAI,MAAQ,EAAA;AAEV,MAAA,cAAA,CAAe,MAAM,CAAA,CAAA;AAAA,KACvB;AAEA,IAAA,IAAI,qBAAwB,GAAA,iBAAA,CAAA;AAC5B,IAAA,IAAI,YAAY,SAAW,EAAA;AACzB,MAAA,MAAM,0BAA0B,aAAc,EAAA,CAAA;AAC9C,MAAwB,qBAAA,GAAA,CAAA,aAAA,EAAgB,QAAQ,CAAA,CAAA,EAAI,uBAAuB,CAAA,CAAA,CAAA;AAC3E,MAAW,UAAA,CAAA,IAAA;AAAA,QACT,wBAAyB,CAAA;AAAA,UACvB,IAAM,EAAA,uBAAA;AAAA,UACN,iBAAA;AAAA,UACA,SAAA;AAAA,UACA,QAAA;AAAA,SACD,CAAA;AAAA,OACH,CAAA;AAAA,KACF;AAEA,IAAmB,kBAAA,CAAA;AAAA,MACjB,QAAA,EAAU,KAAK,KAAM,CAAA,QAAA;AAAA,MACrB,iBAAmB,EAAA,qBAAA;AAAA,MACnB,OAAA;AAAA,KACD,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AACH,CAAA;AAGO,SAAS,oBACd,iBACmB,EAAA;AACnB,EAAM,MAAA,gBAAA,uBAAuB,GAG3B,EAAA,CAAA;AAEF,EAAA,MAAM,gCAAuB,CAAA,MAAA;AAC3B,IAAA,IAAI,YAAe,GAAA,CAAA,CAAA;AACnB,IAAO,OAAA,MAAM,OAAO,YAAc,EAAA,CAAA,CAAA;AAAA,GACjC,GAAA,CAAA;AAEH,EAAM,MAAA,mBAAA,GAAsB,CAAC,MAAkC,KAAA;AAC7D,IAAI,IAAA,UAAA,GAAa,gBAAiB,CAAA,GAAA,CAAI,MAAM,CAAA,CAAA;AAC5C,IAAA,IAAI,CAAC,UAAY,EAAA;AACf,MAAA,UAAA,GAAa,EAAC,CAAA;AACd,MAAiB,gBAAA,CAAA,GAAA,CAAI,QAAQ,UAAU,CAAA,CAAA;AAAA,KACzC;AACA,IAAO,OAAA,UAAA,CAAA;AAAA,GACT,CAAA;AAEA,EAAA,KAAA,CAAM,QAAS,CAAA,OAAA;AAAA,IACb,kBAAkB,KAAM,CAAA,QAAA;AAAA,IACxB,CAAC,KAAqB,KAAA;AAEpB,MAAA,IAAI,CAAC,KAAM,CAAA,cAAA,CAAe,KAAK,CAAK,IAAA,KAAA,CAAM,SAAS,KAAO,EAAA;AACxD,QAAA,OAAA;AAAA,OACF;AAEA,MAAM,MAAA,YAAA,GAAe,MAAM,KAAM,CAAA,OAAA,CAAA;AACjC,MAAM,MAAA,IAAA,GAA2B,MAAM,KAAM,CAAA,IAAA,CAAA;AAC7C,MAAA,MAAM,MAAS,GAAA,gBAAA;AAAA,QACb,YAAA;AAAA,QACA,aAAA;AAAA,OACF,CAAA;AACA,MAAA,MAAM,QAAW,GAAA,gBAAA;AAAA,QACf,YAAA;AAAA,QACA,iBAAA;AAAA,OACF,CAAA;AACA,MAAI,IAAA,CAAC,MAAU,IAAA,CAAC,IAAM,EAAA;AACpB,QAAA,OAAA;AAAA,OACF;AAEA,MAAM,MAAA,UAAA,GAAa,oBAAoB,MAAM,CAAA,CAAA;AAC7C,MAAA,MAAM,iBAAoB,GAAA,UAAA,CAAW,MAAS,GAAA,aAAA,EAAkB,GAAA,KAAA,CAAA,CAAA;AAChE,MAAM,MAAA,eAAA,GAAkB,CAAQ,KAAA,EAAA,MAAA,CAAO,KAAM,EAAC,GAC5C,iBAAoB,GAAA,CAAA,CAAA,EAAI,iBAAiB,CAAA,CAAA,GAAK,iBAChD,CAAA,CAAA,CAAA;AAEA,MAAW,UAAA,CAAA,IAAA;AAAA,QACT,mBAAoB,CAAA;AAAA,UAClB,IAAM,EAAA,iBAAA;AAAA,UACN,WAAA,EAAa,KAAK,CAAC,CAAA,KAAM,MAAM,IAAK,CAAA,KAAA,CAAM,CAAC,CAAI,GAAA,IAAA;AAAA,UAC/C,QAAU,EAAA,QAAA,GAAW,qBAAsB,CAAA,QAAQ,CAAI,GAAA,KAAA,CAAA;AAAA,UACvD,MAAQ,EAAA;AAAA,YACN,mBAAmB,oBAAqB,CAAA;AAAA,cACtC,SAAA,EAAW,iBAAkB,CAAA,SAAA,CAAU,QAAS,EAAA;AAAA,cAChD,QAAA,EAAU,iBAAkB,CAAA,QAAA,CAAS,QAAS,EAAA;AAAA,aAC/C,CAAA;AAAA,WACH;AAAA,UACA,QAAQ,YACN,aAAA;AAAA,YACE,KAAA,CAAM,MAAM,QACV,mBAAA,KAAA,CAAA,aAAA,CAAC,8BACE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,MAAK,GAAI,EAAA,OAAA,EAAS,gCACtB,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,MAAK,GAAI,EAAA,OAAA,EAAS,MAAM,KAAM,CAAA,QAAA,EAAU,CACjD,CACF,CAEA,GAAA,YAAA;AAAA,WAEJ;AAAA,SACH,CAAA;AAAA,OACH,CAAA;AAEA,MAAmB,kBAAA,CAAA;AAAA,QACjB,QAAA,EAAU,MAAM,KAAM,CAAA,QAAA;AAAA,QACtB,iBAAmB,EAAA,eAAA;AAAA,QACnB,OAAS,EAAA;AAAA,UACP,QAAA,EAAU,OAAO,KAAM,EAAA;AAAA,UACvB,UAAA;AAAA,UACA,aAAA;AAAA,UACA,cAAgB,EAAA,mBAAA;AAAA,SAClB;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,GACF,CAAA;AAEA,EAAO,OAAA,KAAA,CAAM,IAAK,CAAA,gBAAgB,CAAE,CAAA,GAAA;AAAA,IAAI,CAAC,CAAC,MAAQ,EAAA,UAAU,CAAG,KAAA;AAhPjE,MAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAiPI,MAAa,OAAA,YAAA,CAAA;AAAA,QACX,EAAA,EAAI,OAAO,KAAM,EAAA;AAAA,QACjB,UAAY,EAAA;AAAA,UACV,GAAG,UAAA;AAAA,UACH,GAAG,KAAM,CAAA,IAAA,CAAK,MAAO,CAAA,OAAA,EAAS,CAAE,CAAA,GAAA;AAAA,YAAI,CAClC,OAAA,KAAA,kBAAA,CAAmB,EAAE,OAAA,EAAS,CAAA;AAAA,WAChC;AAAA,SACF;AAAA,QACA,QAAQ,sBAAuB,CAAA,CAAA,EAAA,GAAA,MAAA,CAAO,MAAP,KAAA,IAAA,GAAA,EAAA,GAAiB,EAAE,CAAA;AAAA,QAClD,gBAAgB,sBAAuB,CAAA,CAAA,EAAA,GAAA,MAAA,CAAO,cAAP,KAAA,IAAA,GAAA,EAAA,GAAyB,EAAE,CAAA;AAAA,OACnE,CAAA,CAAA;AAAA,KAAA;AAAA,GACH,CAAA;AACF;;AC5NA,SAAS,cAAA,CACP,QACA,EAAA,QAAA,EACA,WAC+C,EAAA;AAC/C,EAAA,OAAO,QAAS,CAAA,OAAA,CAAQ,QAAQ,CAAA,CAAE,QAAQ,CAAQ,IAAA,KAAA;AAChD,IAAI,IAAA,CAAC,cAAyC,CAAA,IAAI,CAAG,EAAA;AACnD,MAAA,OAAO,EAAC,CAAA;AAAA,KACV;AAEA,IAAI,IAAA,IAAA,CAAK,SAAS,QAAU,EAAA;AAC1B,MAAA,OAAO,cAAe,CAAA,IAAA,CAAK,KAAM,CAAA,QAAA,EAAU,UAAU,WAAW,CAAA,CAAA;AAAA,KAClE;AAEA,IAAA,IAAI,QAAa,KAAA,KAAA,CAAA,IAAa,QAAS,CAAA,IAAI,CAAG,EAAA;AAC5C,MAAA,OAAO,CAAC,IAAI,CAAA,CAAA;AAAA,KACd;AAEA,IAAA,IAAI,WAAa,EAAA;AACf,MAAM,MAAA,IAAI,MAAM,WAAW,CAAA,CAAA;AAAA,KAC7B;AAEA,IAAA,OAAO,cAAe,CAAA,IAAA,CAAK,KAAM,CAAA,QAAA,EAAU,UAAU,WAAW,CAAA,CAAA;AAAA,GACjE,CAAA,CAAA;AACH,CAAA;AAGO,SAAS,iBACd,WACmB,EAAA;AACnB,EAAA,IAAI,gBAAiB,CAAA,WAAA,EAAa,WAAW,CAAA,KAAM,YAAc,EAAA;AAC/D,IAAA,OAAO,oBAAoB,WAAW,CAAA,CAAA;AAAA,GACxC;AAEA,EAAA,MAAM,YAAe,GAAA,cAAA;AAAA,IACnB,WAAA;AAAA,IACA,CAAM,EAAA,KAAA,gBAAA,CAAiB,EAAI,EAAA,WAAW,CAAM,KAAA,WAAA;AAAA,GAC9C,CAAA;AACA,EAAI,IAAA,YAAA,CAAa,WAAW,CAAG,EAAA;AAC7B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,+HAAA;AAAA,KACF,CAAA;AAAA,GACF;AAEA,EAAA,MAAM,OAAU,GAAA,cAAA;AAAA,IACd,YAAA,CAAa,CAAC,CAAA,CAAE,KAAM,CAAA,QAAA;AAAA,IACtB,CACE,EAAA,KAAA,OAAA,CAAQ,EAAG,CAAA,KAAA,CAAM,QAAQ,CACzB,IAAA,cAAA;AAAA,MACE,GAAG,KAAM,CAAA,QAAA;AAAA,MACT,CAAW,OAAA,KAAA,gBAAA,CAAiB,OAAS,EAAA,WAAW,CAAM,KAAA,YAAA;AAAA,MACtD,MAAW,KAAA,CAAA;AAAA,GACjB,CAAA;AACA,EAAI,IAAA,OAAA,CAAQ,WAAW,CAAG,EAAA;AACxB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,4JAAA;AAAA,KACF,CAAA;AAAA,GACF;AACA,EAAM,MAAA,CAAC,MAAM,CAAI,GAAA,OAAA,CAAA;AAEjB,EAAA,MAAM,SAAY,GAAA,cAAA;AAAA,IAChB,OAAA,CAAQ,CAAC,CAAA,CAAE,KAAM,CAAA,QAAA;AAAA,IACjB,CAAM,EAAA,KAAA,gBAAA,CAAiB,EAAI,EAAA,WAAW,CAAM,KAAA,YAAA;AAAA,GAC9C,CAAA;AACA,EAAI,IAAA,SAAA,CAAU,WAAW,CAAG,EAAA;AAC1B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,4DAAA;AAAA,KACF,CAAA;AAAA,GACF;AACA,EAAM,MAAA,CAAC,QAAQ,CAAI,GAAA,SAAA,CAAA;AAEnB,EAAA,MAAM,qBAAqB,eAAgB,CAAA;AAAA,IACzC,SAAW,EAAA,KAAA;AAAA,IACX,IAAM,EAAA,QAAA;AAAA,IACN,QAAU,EAAA,EAAE,EAAI,EAAA,KAAA,EAAO,OAAO,MAAO,EAAA;AAAA,IACrC,MAAQ,EAAA;AAAA,MACN,OAAS,EAAA,oBAAA;AAAA,QACP;AAAA,UACE,SAAS,iBAAkB,CAAA,YAAA;AAAA,SAC7B;AAAA,QACA,EAAE,WAAW,IAAK,EAAA;AAAA,OACpB;AAAA,KACF;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,SAAS,iBAAkB,CAAA,YAAA;AAAA,KAC7B;AAAA,IACA,OAAA,CAAQ,EAAE,MAAA,EAAU,EAAA;AAElB,MAAO,OAAA;AAAA,QACL,SAAS,KAAM,CAAA,YAAA;AAAA,UACb,MAAA;AAAA,UACA,KAAA,CAAA;AAAA,UACA,MAAA,CAAO,QAAQ,MAAO,CAAA,OAAA;AAAA,SACxB;AAAA,OACF,CAAA;AAAA,KACF;AAAA,GACD,CAAA,CAAA;AACD,EAAA,MAAM,kBAAkB,eAAgB,CAAA;AAAA,IACtC,SAAW,EAAA,KAAA;AAAA,IACX,IAAM,EAAA,KAAA;AAAA,IACN,QAAU,EAAA,EAAE,EAAI,EAAA,YAAA,EAAc,OAAO,KAAM,EAAA;AAAA,IAC3C,QAAQ,EAAC;AAAA,IACT,OAAA,EAAS,OAAO,EAAC,CAAA;AAAA,IACjB,QAAU,EAAA,IAAA;AAAA,GACX,CAAA,CAAA;AAED,EAAM,MAAA,eAAA,GAAkB,oBAAoB,QAAQ,CAAA,CAAA;AAEpD,EAAO,OAAA;AAAA,IACL,GAAG,eAAA;AAAA,IACH,wBAAyB,CAAA;AAAA,MACvB,UAAA,EAAY,CAAC,kBAAA,EAAoB,eAAe,CAAA;AAAA,KACjD,CAAA;AAAA,GACH,CAAA;AACF;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/core-compat-api",
|
|
3
|
-
"version": "0.0.0-nightly-
|
|
3
|
+
"version": "0.0.0-nightly-20240120021525",
|
|
4
4
|
"main": "dist/index.esm.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@backstage/core-app-api": "^1.11.3",
|
|
27
27
|
"@backstage/core-plugin-api": "^1.8.2",
|
|
28
|
-
"@backstage/frontend-plugin-api": "^0.0.0-nightly-
|
|
28
|
+
"@backstage/frontend-plugin-api": "^0.0.0-nightly-20240120021525",
|
|
29
29
|
"@backstage/version-bridge": "^1.0.7",
|
|
30
30
|
"@types/react": "^16.13.1 || ^17.0.0"
|
|
31
31
|
},
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@backstage/cli": "^0.0.0-nightly-
|
|
38
|
-
"@backstage/frontend-app-api": "^0.0.0-nightly-
|
|
39
|
-
"@backstage/frontend-test-utils": "^0.0.0-nightly-
|
|
40
|
-
"@backstage/plugin-catalog": "^0.0.0-nightly-
|
|
41
|
-
"@backstage/plugin-puppetdb": "^0.0.0-nightly-
|
|
37
|
+
"@backstage/cli": "^0.0.0-nightly-20240120021525",
|
|
38
|
+
"@backstage/frontend-app-api": "^0.0.0-nightly-20240120021525",
|
|
39
|
+
"@backstage/frontend-test-utils": "^0.0.0-nightly-20240120021525",
|
|
40
|
+
"@backstage/plugin-catalog": "^0.0.0-nightly-20240120021525",
|
|
41
|
+
"@backstage/plugin-puppetdb": "^0.0.0-nightly-20240120021525",
|
|
42
42
|
"@backstage/plugin-stackstorm": "^0.1.10",
|
|
43
43
|
"@oriflame/backstage-plugin-score-card": "^0.7.0",
|
|
44
44
|
"@testing-library/jest-dom": "^6.0.0",
|