@backstage/frontend-plugin-api 0.13.4 → 0.14.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +35 -2
  2. package/dist/blueprints/AnalyticsImplementationBlueprint.esm.js +1 -1
  3. package/dist/blueprints/AnalyticsImplementationBlueprint.esm.js.map +1 -1
  4. package/dist/components/ExtensionBoundary.esm.js +1 -1
  5. package/dist/components/ExtensionBoundary.esm.js.map +1 -1
  6. package/dist/index.d.ts +68 -265
  7. package/dist/index.esm.js +0 -8
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/wiring/constants.esm.js +4 -0
  10. package/dist/wiring/constants.esm.js.map +1 -0
  11. package/dist/wiring/createExtension.esm.js.map +1 -1
  12. package/dist/wiring/createExtensionInput.esm.js +2 -1
  13. package/dist/wiring/createExtensionInput.esm.js.map +1 -1
  14. package/dist/wiring/createFrontendPlugin.esm.js +7 -0
  15. package/dist/wiring/createFrontendPlugin.esm.js.map +1 -1
  16. package/dist/wiring/resolveExtensionDefinition.esm.js.map +1 -1
  17. package/dist/wiring/resolveInputOverrides.esm.js.map +1 -1
  18. package/package.json +9 -9
  19. package/dist/blueprints/AppRootWrapperBlueprint.esm.js +0 -21
  20. package/dist/blueprints/AppRootWrapperBlueprint.esm.js.map +0 -1
  21. package/dist/blueprints/IconBundleBlueprint.esm.js +0 -21
  22. package/dist/blueprints/IconBundleBlueprint.esm.js.map +0 -1
  23. package/dist/blueprints/NavContentBlueprint.esm.js +0 -23
  24. package/dist/blueprints/NavContentBlueprint.esm.js.map +0 -1
  25. package/dist/blueprints/RouterBlueprint.esm.js +0 -21
  26. package/dist/blueprints/RouterBlueprint.esm.js.map +0 -1
  27. package/dist/blueprints/SignInPageBlueprint.esm.js +0 -52
  28. package/dist/blueprints/SignInPageBlueprint.esm.js.map +0 -1
  29. package/dist/blueprints/SwappableComponentBlueprint.esm.js +0 -27
  30. package/dist/blueprints/SwappableComponentBlueprint.esm.js.map +0 -1
  31. package/dist/blueprints/ThemeBlueprint.esm.js +0 -21
  32. package/dist/blueprints/ThemeBlueprint.esm.js.map +0 -1
  33. package/dist/blueprints/TranslationBlueprint.esm.js +0 -21
  34. package/dist/blueprints/TranslationBlueprint.esm.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,10 +1,43 @@
1
1
  # @backstage/frontend-plugin-api
2
2
 
3
- ## 0.13.4
3
+ ## 0.14.0-next.1
4
+
5
+ ### Minor Changes
6
+
7
+ - bb9b471: Plugin IDs that do not match the standard format are deprecated (letters, digits, and dashes only, starting with a letter). Plugin IDs that do no match this format will be rejected in a future release.
8
+ - 10ebed4: **BREAKING**: Removed type support for multiple attachment points in the `ExtensionDefinitionAttachTo` type. Extensions can no longer specify an array of attachment points in the `attachTo` property.
9
+
10
+ The runtime still supports multiple attachment points for backward compatibility with existing compiled code, but new code will receive type errors if attempting to use this pattern.
11
+
12
+ Extensions that previously used multiple attachment points should migrate to using a Utility API pattern instead. See the [Sharing Extensions Across Multiple Locations](https://backstage.io/docs/frontend-system/architecture/27-sharing-extensions) guide for the recommended approach.
13
+
14
+ ## 0.14.0-next.0
15
+
16
+ ### Minor Changes
17
+
18
+ - c38b74d: **BREAKING**: The following blueprints have been removed and are now only available from `@backstage/plugin-app-react`:
19
+
20
+ - `IconBundleBlueprint`
21
+ - `NavContentBlueprint`
22
+ - `RouterBlueprint`
23
+ - `SignInPageBlueprint`
24
+ - `SwappableComponentBlueprint`
25
+ - `ThemeBlueprint`
26
+ - `TranslationBlueprint`
4
27
 
5
28
  ### Patch Changes
6
29
 
7
- - 5683c85: Bump to latest zod to ensure it has the latest features
30
+ - 7edb810: Added a new `internal` option to `createExtensionInput` that marks the input as only allowing attachments from the same plugin.
31
+ - 9554c36: **DEPRECATED**: Multiple attachment points for extensions have been deprecated. The functionality continues to work for backward compatibility, but will log a deprecation warning and be removed in a future release.
32
+
33
+ Extensions using array attachment points should migrate to using Utility APIs instead. See the [Sharing Extensions Across Multiple Locations](https://backstage.io/docs/frontend-system/architecture/27-sharing-extensions) guide for the recommended pattern.
34
+
35
+ - 53b6549: Plugins in the new frontend system now have a `pluginId` field rather than `id` to better align with naming conventions used throughout the frontend and backend systems. The old field is still present but marked as deprecated. All internal code has been updated to prefer `pluginId` while maintaining backward compatibility by falling back to `id` when needed.
36
+ - 69d880e: Bump to latest zod to ensure it has the latest features
37
+ - Updated dependencies
38
+ - @backstage/errors@1.2.7
39
+ - @backstage/types@1.2.2
40
+ - @backstage/version-bridge@1.0.11
8
41
 
9
42
  ## 0.13.3
10
43
 
@@ -9,7 +9,7 @@ const factoryDataRef = createExtensionDataRef().with({
9
9
  });
10
10
  const AnalyticsImplementationBlueprint = createExtensionBlueprint({
11
11
  kind: "analytics",
12
- attachTo: [{ id: "api:app/analytics", input: "implementations" }],
12
+ attachTo: { id: "api:app/analytics", input: "implementations" },
13
13
  output: [factoryDataRef],
14
14
  dataRefs: {
15
15
  factory: factoryDataRef
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsImplementationBlueprint.esm.js","sources":["../../src/blueprints/AnalyticsImplementationBlueprint.ts"],"sourcesContent":["/*\n * Copyright 2025 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 { AnalyticsImplementation, TypesToApiRefs } from '../apis';\nimport {\n createExtensionBlueprint,\n createExtensionBlueprintParams,\n createExtensionDataRef,\n} from '../wiring';\n\n/** @public */\nexport type AnalyticsImplementationFactory<\n Deps extends { [name in string]: unknown } = {},\n> = {\n deps: TypesToApiRefs<Deps>;\n factory(deps: Deps): AnalyticsImplementation;\n};\n\nconst factoryDataRef =\n createExtensionDataRef<AnalyticsImplementationFactory>().with({\n id: 'core.analytics.factory',\n });\n\n/**\n * Creates analytics implementations.\n *\n * @public\n */\nexport const AnalyticsImplementationBlueprint = createExtensionBlueprint({\n kind: 'analytics',\n attachTo: [{ id: 'api:app/analytics', input: 'implementations' }],\n output: [factoryDataRef],\n dataRefs: {\n factory: factoryDataRef,\n },\n defineParams: <TDeps extends { [name in string]: unknown }>(\n params: AnalyticsImplementationFactory<TDeps>,\n ) => createExtensionBlueprintParams(params as AnalyticsImplementationFactory),\n *factory(params) {\n yield factoryDataRef(params);\n },\n});\n"],"names":[],"mappings":";;;;;;AA+BA,MAAM,cAAA,GACJ,sBAAA,EAAuD,CAAE,IAAA,CAAK;AAAA,EAC5D,EAAA,EAAI;AACN,CAAC,CAAA;AAOI,MAAM,mCAAmC,wBAAA,CAAyB;AAAA,EACvE,IAAA,EAAM,WAAA;AAAA,EACN,UAAU,CAAC,EAAE,IAAI,mBAAA,EAAqB,KAAA,EAAO,mBAAmB,CAAA;AAAA,EAChE,MAAA,EAAQ,CAAC,cAAc,CAAA;AAAA,EACvB,QAAA,EAAU;AAAA,IACR,OAAA,EAAS;AAAA,GACX;AAAA,EACA,YAAA,EAAc,CACZ,MAAA,KACG,8BAAA,CAA+B,MAAwC,CAAA;AAAA,EAC5E,CAAC,QAAQ,MAAA,EAAQ;AACf,IAAA,MAAM,eAAe,MAAM,CAAA;AAAA,EAC7B;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"AnalyticsImplementationBlueprint.esm.js","sources":["../../src/blueprints/AnalyticsImplementationBlueprint.ts"],"sourcesContent":["/*\n * Copyright 2025 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 { AnalyticsImplementation, TypesToApiRefs } from '../apis';\nimport {\n createExtensionBlueprint,\n createExtensionBlueprintParams,\n createExtensionDataRef,\n} from '../wiring';\n\n/** @public */\nexport type AnalyticsImplementationFactory<\n Deps extends { [name in string]: unknown } = {},\n> = {\n deps: TypesToApiRefs<Deps>;\n factory(deps: Deps): AnalyticsImplementation;\n};\n\nconst factoryDataRef =\n createExtensionDataRef<AnalyticsImplementationFactory>().with({\n id: 'core.analytics.factory',\n });\n\n/**\n * Creates analytics implementations.\n *\n * @public\n */\nexport const AnalyticsImplementationBlueprint = createExtensionBlueprint({\n kind: 'analytics',\n attachTo: { id: 'api:app/analytics', input: 'implementations' },\n output: [factoryDataRef],\n dataRefs: {\n factory: factoryDataRef,\n },\n defineParams: <TDeps extends { [name in string]: unknown }>(\n params: AnalyticsImplementationFactory<TDeps>,\n ) => createExtensionBlueprintParams(params as AnalyticsImplementationFactory),\n *factory(params) {\n yield factoryDataRef(params);\n },\n});\n"],"names":[],"mappings":";;;;;;AA+BA,MAAM,cAAA,GACJ,sBAAA,EAAuD,CAAE,IAAA,CAAK;AAAA,EAC5D,EAAA,EAAI;AACN,CAAC,CAAA;AAOI,MAAM,mCAAmC,wBAAA,CAAyB;AAAA,EACvE,IAAA,EAAM,WAAA;AAAA,EACN,QAAA,EAAU,EAAE,EAAA,EAAI,mBAAA,EAAqB,OAAO,iBAAA,EAAkB;AAAA,EAC9D,MAAA,EAAQ,CAAC,cAAc,CAAA;AAAA,EACvB,QAAA,EAAU;AAAA,IACR,OAAA,EAAS;AAAA,GACX;AAAA,EACA,YAAA,EAAc,CACZ,MAAA,KACG,8BAAA,CAA+B,MAAwC,CAAA;AAAA,EAC5E,CAAC,QAAQ,MAAA,EAAQ;AACf,IAAA,MAAM,eAAe,MAAM,CAAA;AAAA,EAC7B;AACF,CAAC;;;;"}
@@ -64,7 +64,7 @@ function ExtensionBoundary(props) {
64
64
  node.instance?.getData(coreExtensionData.routePath)
65
65
  );
66
66
  const plugin = node.spec.plugin;
67
- const pluginId = plugin.id ?? "app";
67
+ const pluginId = plugin.pluginId ?? "app";
68
68
  const pluginWrapperApi = useOptionalPluginWrapperApi();
69
69
  const PluginWrapper = useMemo(() => {
70
70
  return pluginWrapperApi?.getPluginWrapper(pluginId);
@@ -1 +1 @@
1
- {"version":3,"file":"ExtensionBoundary.esm.js","sources":["../../src/components/ExtensionBoundary.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n PropsWithChildren,\n ReactNode,\n Suspense,\n useEffect,\n useMemo,\n lazy as reactLazy,\n} from 'react';\nimport { AnalyticsContext, useAnalytics } from '../analytics';\nimport { ErrorDisplayBoundary } from './ErrorDisplayBoundary';\nimport { ErrorApiBoundary } from './ErrorApiBoundary';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker';\nimport { AppNode, ErrorApi, errorApiRef, useApi } from '../apis';\nimport {\n PluginWrapperApi,\n pluginWrapperApiRef,\n} from '../apis/definitions/PluginWrapperApi';\nimport { coreExtensionData } from '../wiring';\nimport { AppNodeProvider } from './AppNodeProvider';\nimport { Progress } from './DefaultSwappableComponents';\n\nfunction useOptionalErrorApi(): ErrorApi | undefined {\n try {\n return useApi(errorApiRef);\n } catch {\n return undefined;\n }\n}\n\nfunction useOptionalPluginWrapperApi(): PluginWrapperApi | undefined {\n try {\n return useApi(pluginWrapperApiRef);\n } catch {\n return undefined;\n }\n}\ntype RouteTrackerProps = PropsWithChildren<{\n enabled?: boolean;\n}>;\n\nconst RouteTracker = (props: RouteTrackerProps) => {\n const { enabled, children } = props;\n const analytics = useAnalytics();\n\n // This event, never exposed to end-users of the analytics API,\n // helps inform which extension metadata gets associated with a\n // navigation event when the route navigated to is a gathered\n // mountpoint.\n useEffect(() => {\n if (enabled) {\n analytics.captureEvent(routableExtensionRenderedEvent, '');\n }\n }, [analytics, enabled]);\n\n return <>{children}</>;\n};\n\n/** @public */\nexport interface ExtensionBoundaryProps {\n errorPresentation?: 'error-api' | 'error-display';\n node: AppNode;\n children: ReactNode;\n}\n\n/** @public */\nexport function ExtensionBoundary(props: ExtensionBoundaryProps) {\n const { node, children } = props;\n\n const errorApi = useOptionalErrorApi();\n\n const hasRoutePathOutput = Boolean(\n node.instance?.getData(coreExtensionData.routePath),\n );\n\n const plugin = node.spec.plugin;\n const pluginId = plugin.id ?? 'app';\n\n const pluginWrapperApi = useOptionalPluginWrapperApi();\n\n const PluginWrapper = useMemo(() => {\n return pluginWrapperApi?.getPluginWrapper(pluginId);\n }, [pluginWrapperApi, pluginId]);\n\n // Skipping \"routeRef\" attribute in the new system, the extension \"id\" should provide more insight\n const attributes = {\n extensionId: node.spec.id,\n pluginId,\n };\n\n let content = (\n <AnalyticsContext attributes={attributes}>\n <RouteTracker enabled={hasRoutePathOutput}>{children}</RouteTracker>\n </AnalyticsContext>\n );\n\n if (PluginWrapper) {\n content = <PluginWrapper>{content}</PluginWrapper>;\n }\n\n if (props.errorPresentation === 'error-api') {\n content = (\n <ErrorApiBoundary node={node} errorApi={errorApi}>\n {content}\n </ErrorApiBoundary>\n );\n } else {\n content = (\n <ErrorDisplayBoundary plugin={plugin}>{content}</ErrorDisplayBoundary>\n );\n }\n\n return (\n <AppNodeProvider node={node}>\n <Suspense fallback={<Progress />}>{content}</Suspense>\n </AppNodeProvider>\n );\n}\n\n/** @public */\nexport namespace ExtensionBoundary {\n export function lazy(\n appNode: AppNode,\n loader: () => Promise<JSX.Element>,\n ): JSX.Element {\n const ExtensionComponent = reactLazy(() =>\n loader().then(element => ({ default: () => element })),\n );\n return (\n <ExtensionBoundary node={appNode}>\n <ExtensionComponent />\n </ExtensionBoundary>\n );\n }\n\n export function lazyComponent<TProps extends {}>(\n appNode: AppNode,\n loader: () => Promise<(props: TProps) => JSX.Element>,\n ): (props: TProps) => JSX.Element {\n const ExtensionComponent = reactLazy(() =>\n loader().then(Component => ({ default: Component })),\n ) as unknown as React.ComponentType<TProps>;\n\n return (props: TProps) => (\n <ExtensionBoundary node={appNode}>\n <ExtensionComponent {...props} />\n </ExtensionBoundary>\n );\n }\n}\n"],"names":["ExtensionBoundary","lazy","reactLazy"],"mappings":"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"}
1
+ {"version":3,"file":"ExtensionBoundary.esm.js","sources":["../../src/components/ExtensionBoundary.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n PropsWithChildren,\n ReactNode,\n Suspense,\n useEffect,\n useMemo,\n lazy as reactLazy,\n} from 'react';\nimport { AnalyticsContext, useAnalytics } from '../analytics';\nimport { ErrorDisplayBoundary } from './ErrorDisplayBoundary';\nimport { ErrorApiBoundary } from './ErrorApiBoundary';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker';\nimport { AppNode, ErrorApi, errorApiRef, useApi } from '../apis';\nimport {\n PluginWrapperApi,\n pluginWrapperApiRef,\n} from '../apis/definitions/PluginWrapperApi';\nimport { coreExtensionData } from '../wiring';\nimport { AppNodeProvider } from './AppNodeProvider';\nimport { Progress } from './DefaultSwappableComponents';\n\nfunction useOptionalErrorApi(): ErrorApi | undefined {\n try {\n return useApi(errorApiRef);\n } catch {\n return undefined;\n }\n}\n\nfunction useOptionalPluginWrapperApi(): PluginWrapperApi | undefined {\n try {\n return useApi(pluginWrapperApiRef);\n } catch {\n return undefined;\n }\n}\ntype RouteTrackerProps = PropsWithChildren<{\n enabled?: boolean;\n}>;\n\nconst RouteTracker = (props: RouteTrackerProps) => {\n const { enabled, children } = props;\n const analytics = useAnalytics();\n\n // This event, never exposed to end-users of the analytics API,\n // helps inform which extension metadata gets associated with a\n // navigation event when the route navigated to is a gathered\n // mountpoint.\n useEffect(() => {\n if (enabled) {\n analytics.captureEvent(routableExtensionRenderedEvent, '');\n }\n }, [analytics, enabled]);\n\n return <>{children}</>;\n};\n\n/** @public */\nexport interface ExtensionBoundaryProps {\n errorPresentation?: 'error-api' | 'error-display';\n node: AppNode;\n children: ReactNode;\n}\n\n/** @public */\nexport function ExtensionBoundary(props: ExtensionBoundaryProps) {\n const { node, children } = props;\n\n const errorApi = useOptionalErrorApi();\n\n const hasRoutePathOutput = Boolean(\n node.instance?.getData(coreExtensionData.routePath),\n );\n\n const plugin = node.spec.plugin;\n const pluginId = plugin.pluginId ?? 'app';\n\n const pluginWrapperApi = useOptionalPluginWrapperApi();\n\n const PluginWrapper = useMemo(() => {\n return pluginWrapperApi?.getPluginWrapper(pluginId);\n }, [pluginWrapperApi, pluginId]);\n\n // Skipping \"routeRef\" attribute in the new system, the extension \"id\" should provide more insight\n const attributes = {\n extensionId: node.spec.id,\n pluginId,\n };\n\n let content = (\n <AnalyticsContext attributes={attributes}>\n <RouteTracker enabled={hasRoutePathOutput}>{children}</RouteTracker>\n </AnalyticsContext>\n );\n\n if (PluginWrapper) {\n content = <PluginWrapper>{content}</PluginWrapper>;\n }\n\n if (props.errorPresentation === 'error-api') {\n content = (\n <ErrorApiBoundary node={node} errorApi={errorApi}>\n {content}\n </ErrorApiBoundary>\n );\n } else {\n content = (\n <ErrorDisplayBoundary plugin={plugin}>{content}</ErrorDisplayBoundary>\n );\n }\n\n return (\n <AppNodeProvider node={node}>\n <Suspense fallback={<Progress />}>{content}</Suspense>\n </AppNodeProvider>\n );\n}\n\n/** @public */\nexport namespace ExtensionBoundary {\n export function lazy(\n appNode: AppNode,\n loader: () => Promise<JSX.Element>,\n ): JSX.Element {\n const ExtensionComponent = reactLazy(() =>\n loader().then(element => ({ default: () => element })),\n );\n return (\n <ExtensionBoundary node={appNode}>\n <ExtensionComponent />\n </ExtensionBoundary>\n );\n }\n\n export function lazyComponent<TProps extends {}>(\n appNode: AppNode,\n loader: () => Promise<(props: TProps) => JSX.Element>,\n ): (props: TProps) => JSX.Element {\n const ExtensionComponent = reactLazy(() =>\n loader().then(Component => ({ default: Component })),\n ) as unknown as React.ComponentType<TProps>;\n\n return (props: TProps) => (\n <ExtensionBoundary node={appNode}>\n <ExtensionComponent {...props} />\n </ExtensionBoundary>\n );\n }\n}\n"],"names":["ExtensionBoundary","lazy","reactLazy"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,7 +2,6 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ReactNode, JSX as JSX$1, ComponentType, PropsWithChildren } from 'react';
4
4
  import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
5
- import { IconComponent as IconComponent$1, RouteRef as RouteRef$1 } from '@backstage/frontend-plugin-api';
6
5
  import { Expand, JsonObject, Observable, JsonValue, ExpandRecursive } from '@backstage/types';
7
6
  import { z } from 'zod';
8
7
  import { Config } from '@backstage/config';
@@ -132,9 +131,11 @@ interface ExtensionInput<UExtensionData extends ExtensionDataRef<unknown, string
132
131
  }> = ExtensionDataRef, TConfig extends {
133
132
  singleton: boolean;
134
133
  optional: boolean;
134
+ internal?: boolean;
135
135
  } = {
136
136
  singleton: boolean;
137
137
  optional: boolean;
138
+ internal?: boolean;
138
139
  }> {
139
140
  readonly $$type: '@backstage/ExtensionInput';
140
141
  readonly extensionData: Array<UExtensionData>;
@@ -144,12 +145,59 @@ interface ExtensionInput<UExtensionData extends ExtensionDataRef<unknown, string
144
145
  input: string;
145
146
  }>;
146
147
  }
147
- /** @public */
148
+ /**
149
+ * Creates a new extension input to be passed to the input map of an extension.
150
+ *
151
+ * @remarks
152
+ *
153
+ * Extension inputs created with this function can be passed to any `inputs` map
154
+ * as part of creating or overriding an extension.
155
+ *
156
+ * The array of extension data references defines the data this input expects.
157
+ * If the required data is not provided by the attached extension, the
158
+ * attachment will fail.
159
+ *
160
+ * The `config` object can be used to restrict the behavior and shape of the
161
+ * input. By default an input will accept zero or more extensions from any
162
+ * plugin. The following options are available:
163
+ *
164
+ * - `singleton`: If set to `true`, only one extension can be attached to the
165
+ * input at a time. Additional extensions will trigger an app error and be
166
+ * ignored.
167
+ * - `optional`: If set to `true`, the input is optional and can be omitted,
168
+ * this only has an effect if the `singleton` is set to `true`.
169
+ * - `internal`: If set to `true`, only extensions from the same plugin will be
170
+ * allowed to attach to this input. Other extensions will trigger an app error
171
+ * and be ignored.
172
+ *
173
+ * @param extensionData - The array of extension data references that this input
174
+ * expects.
175
+ * @param config - The configuration object for the input.
176
+ * @returns An extension input declaration.
177
+ * @example
178
+ * ```ts
179
+ * const extension = createExtension({
180
+ * attachTo: { id: 'example-parent', input: 'example-input' },
181
+ * inputs: {
182
+ * content: createExtensionInput([coreExtensionData.reactElement], {
183
+ * singleton: true,
184
+ * }),
185
+ * },
186
+ * output: [coreExtensionData.reactElement],
187
+ * *factory({ inputs }) {
188
+ * const content = inputs.content?.get(coreExtensionData.reactElement);
189
+ * yield coreExtensionData.reactElement(<ContentWrapper>{content}</ContentWrapper>);
190
+ * },
191
+ * });
192
+ * ```
193
+ * @public
194
+ */
148
195
  declare function createExtensionInput<UExtensionData extends ExtensionDataRef<unknown, string, {
149
196
  optional?: true;
150
197
  }>, TConfig extends {
151
198
  singleton?: boolean;
152
199
  optional?: boolean;
200
+ internal?: boolean;
153
201
  }>(extensionData: Array<UExtensionData>, config?: TConfig & {
154
202
  replaces?: Array<{
155
203
  id: string;
@@ -158,6 +206,7 @@ declare function createExtensionInput<UExtensionData extends ExtensionDataRef<un
158
206
  }): ExtensionInput<UExtensionData, {
159
207
  singleton: TConfig['singleton'] extends true ? true : false;
160
208
  optional: TConfig['optional'] extends true ? true : false;
209
+ internal: TConfig['internal'] extends true ? true : false;
161
210
  }>;
162
211
 
163
212
  /** @ignore */
@@ -169,17 +218,21 @@ type ResolvedInputValueOverrides<TInputs extends {
169
218
  [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<any, {
170
219
  optional: infer IOptional extends boolean;
171
220
  singleton: boolean;
221
+ internal?: boolean;
172
222
  }> ? IOptional extends true ? never : KName : never]: TInputs[KName] extends ExtensionInput<infer IDataRefs, {
173
223
  optional: boolean;
174
224
  singleton: infer ISingleton extends boolean;
225
+ internal?: boolean;
175
226
  }> ? ISingleton extends true ? Iterable<ExtensionDataRefToValue<IDataRefs>> : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>> : never;
176
227
  } & {
177
228
  [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<any, {
178
229
  optional: infer IOptional extends boolean;
179
230
  singleton: boolean;
231
+ internal?: boolean;
180
232
  }> ? IOptional extends true ? KName : never : never]?: TInputs[KName] extends ExtensionInput<infer IDataRefs, {
181
233
  optional: boolean;
182
234
  singleton: infer ISingleton extends boolean;
235
+ internal?: boolean;
183
236
  }> ? ISingleton extends true ? Iterable<ExtensionDataRefToValue<IDataRefs>> : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>> : never;
184
237
  }>;
185
238
 
@@ -529,6 +582,15 @@ interface FrontendPlugin<TRoutes extends {
529
582
  [name in string]: ExternalRouteRef;
530
583
  }> {
531
584
  readonly $$type: '@backstage/FrontendPlugin';
585
+ /**
586
+ * The plugin ID.
587
+ */
588
+ readonly pluginId: string;
589
+ /**
590
+ * Deprecated alias for `pluginId`.
591
+ *
592
+ * @deprecated Use `pluginId` instead.
593
+ */
532
594
  readonly id: string;
533
595
  readonly routes: TRoutes;
534
596
  readonly externalRoutes: TExternalRoutes;
@@ -912,11 +974,10 @@ type VerifyExtensionAttachTo<UOutput extends ExtensionDataRef, UParentInput exte
912
974
  *
913
975
  * A standard attachment point declaration will specify the ID of the parent extension, as well as the name of the input to attach to.
914
976
  *
915
- * There are three more advanced forms that are available for more complex use-cases:
977
+ * There are two more advanced forms that are available for more complex use-cases:
916
978
  *
917
979
  * 1. Relative attachment points: using the `relative` property instead of `id`, the attachment point is resolved relative to the current plugin.
918
980
  * 2. Extension input references: using a reference in code to another extension's input in the same plugin. These references are always relative.
919
- * 3. Array of attachment points: an array of attachment points can be used to clone and attach to multiple extensions at once.
920
981
  *
921
982
  * @example
922
983
  * ```ts
@@ -929,12 +990,6 @@ type VerifyExtensionAttachTo<UOutput extends ExtensionDataRef, UParentInput exte
929
990
  * // Attach to a specific input of another extension
930
991
  * const page = ParentBlueprint.make({ ... });
931
992
  * const child = ChildBlueprint.make({ attachTo: page.inputs.children });
932
- *
933
- * // Attach to multiple parents at once
934
- * [
935
- * { id: 'page/home', input: 'widgets' },
936
- * { relative: { kind: 'page' }, input: 'widgets' },
937
- * ]
938
993
  * ```
939
994
  *
940
995
  * @public
@@ -950,18 +1005,7 @@ type ExtensionDefinitionAttachTo<UParentInputs extends ExtensionDataRef = Extens
950
1005
  };
951
1006
  input: string;
952
1007
  id?: never;
953
- } | ExtensionInput<UParentInputs> | Array<{
954
- id: string;
955
- input: string;
956
- relative?: never;
957
- } | {
958
- relative: {
959
- kind?: string;
960
- name?: string;
961
- };
962
- input: string;
963
- id?: never;
964
- } | ExtensionInput<UParentInputs>>;
1008
+ } | ExtensionInput<UParentInputs>;
965
1009
  /** @public */
966
1010
  type CreateExtensionOptions<TKind extends string | undefined, TName extends string | undefined, UOutput extends ExtensionDataRef, TInputs extends {
967
1011
  [inputName in string]: ExtensionInput;
@@ -3190,108 +3234,6 @@ declare const AppRootElementBlueprint: _backstage_frontend_plugin_api.ExtensionB
3190
3234
  dataRefs: never;
3191
3235
  }>;
3192
3236
 
3193
- /**
3194
- * Creates a extensions that render a React wrapper at the app root, enclosing
3195
- * the app layout. This is useful for example for adding global React contexts
3196
- * and similar.
3197
- *
3198
- * @public
3199
- * @deprecated Use {@link @backstage/plugin-app-react#AppRootWrapperBlueprint} instead.
3200
- * If you were using this blueprint to provide a context for your plugin,
3201
- * use `PluginWrapperBlueprint` from `@backstage/frontend-plugin-api/alpha` instead.
3202
- */
3203
- declare const AppRootWrapperBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
3204
- kind: "app-root-wrapper";
3205
- params: {
3206
- /** @deprecated use the `component` parameter instead */
3207
- Component?: [error: "Use the `component` parameter instead"];
3208
- component: (props: {
3209
- children: ReactNode;
3210
- }) => JSX.Element | null;
3211
- };
3212
- output: _backstage_frontend_plugin_api.ExtensionDataRef<(props: {
3213
- children: ReactNode;
3214
- }) => JSX.Element | null, "app.root.wrapper", {}>;
3215
- inputs: {};
3216
- config: {};
3217
- configInput: {};
3218
- dataRefs: {
3219
- component: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(props: {
3220
- children: ReactNode;
3221
- }) => JSX.Element | null, "app.root.wrapper", {}>;
3222
- };
3223
- }>;
3224
-
3225
- /**
3226
- * @public
3227
- * @deprecated Use {@link @backstage/plugin-app-react#IconBundleBlueprint} instead.
3228
- */
3229
- declare const IconBundleBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
3230
- kind: "icon-bundle";
3231
- params: {
3232
- icons: { [key in string]: IconComponent; };
3233
- };
3234
- output: _backstage_frontend_plugin_api.ExtensionDataRef<{
3235
- [x: string]: IconComponent;
3236
- }, "core.icons", {}>;
3237
- inputs: {};
3238
- config: {};
3239
- configInput: {};
3240
- dataRefs: {
3241
- icons: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
3242
- [x: string]: IconComponent;
3243
- }, "core.icons", {}>;
3244
- };
3245
- }>;
3246
-
3247
- /**
3248
- * The props for the {@link NavContentComponent}.
3249
- *
3250
- * @public
3251
- */
3252
- interface NavContentComponentProps {
3253
- /**
3254
- * The nav items available to the component. These are all the items created
3255
- * with the {@link NavItemBlueprint} in the app.
3256
- *
3257
- * In addition to the original properties from the nav items, these also
3258
- * include a resolved route path as `to`, and duplicated `title` as `text` to
3259
- * simplify rendering.
3260
- */
3261
- items: Array<{
3262
- icon: IconComponent$1;
3263
- title: string;
3264
- routeRef: RouteRef$1<undefined>;
3265
- to: string;
3266
- text: string;
3267
- }>;
3268
- }
3269
- /**
3270
- * A component that renders the nav bar content, to be passed to the {@link NavContentBlueprint}.
3271
- *
3272
- * @public
3273
- */
3274
- type NavContentComponent = (props: NavContentComponentProps) => JSX.Element | null;
3275
- /**
3276
- * Creates an extension that replaces the entire nav bar with your own component.
3277
- *
3278
- * @public
3279
- * @deprecated Use {@link @backstage/plugin-app-react#NavContentBlueprint} instead.
3280
- */
3281
- declare const NavContentBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
3282
- kind: "nav-content";
3283
- params: {
3284
- component: NavContentComponent;
3285
- };
3286
- output: _backstage_frontend_plugin_api.ExtensionDataRef<NavContentComponent, "core.nav-content.component", {}>;
3287
- inputs: {};
3288
- config: {};
3289
- configInput: {};
3290
- dataRefs: {
3291
- component: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<NavContentComponent, "core.nav-content.component", {}>;
3292
- };
3293
- }>;
3294
-
3295
3237
  /**
3296
3238
  * Creates extensions that make up the items of the nav bar.
3297
3239
  *
@@ -3350,144 +3292,5 @@ declare const PageBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
3350
3292
  dataRefs: never;
3351
3293
  }>;
3352
3294
 
3353
- /**
3354
- * @public
3355
- * @deprecated Use {@link @backstage/plugin-app-react#RouterBlueprint} instead.
3356
- */
3357
- declare const RouterBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
3358
- kind: "app-router-component";
3359
- params: {
3360
- /** @deprecated use the `component` parameter instead */
3361
- Component?: [error: "Use the `component` parameter instead"];
3362
- component: (props: {
3363
- children: ReactNode;
3364
- }) => JSX.Element | null;
3365
- };
3366
- output: _backstage_frontend_plugin_api.ExtensionDataRef<(props: {
3367
- children: ReactNode;
3368
- }) => JSX.Element | null, "app.router.wrapper", {}>;
3369
- inputs: {};
3370
- config: {};
3371
- configInput: {};
3372
- dataRefs: {
3373
- component: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(props: {
3374
- children: ReactNode;
3375
- }) => JSX.Element | null, "app.router.wrapper", {}>;
3376
- };
3377
- }>;
3378
-
3379
- /**
3380
- * Props for the `SignInPage` component.
3381
- *
3382
- * @public
3383
- */
3384
- type SignInPageProps = {
3385
- /**
3386
- * Set the IdentityApi on successful sign-in. This should only be called once.
3387
- */
3388
- onSignInSuccess(identityApi: IdentityApi): void;
3389
- /**
3390
- * The children to render.
3391
- */
3392
- children?: ReactNode;
3393
- };
3394
- /**
3395
- * Creates an extension that replaces the sign in page.
3396
- *
3397
- * @public
3398
- * @deprecated Use {@link @backstage/plugin-app-react#SignInPageBlueprint} instead.
3399
- */
3400
- declare const SignInPageBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
3401
- kind: "sign-in-page";
3402
- params: {
3403
- loader: () => Promise<ComponentType<SignInPageProps>>;
3404
- };
3405
- output: _backstage_frontend_plugin_api.ExtensionDataRef<ComponentType<SignInPageProps>, "core.sign-in-page.component", {}>;
3406
- inputs: {};
3407
- config: {};
3408
- configInput: {};
3409
- dataRefs: {
3410
- component: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<ComponentType<SignInPageProps>, "core.sign-in-page.component", {}>;
3411
- };
3412
- }>;
3413
-
3414
- /**
3415
- * Creates an extension that adds/replaces an app theme.
3416
- *
3417
- * @public
3418
- * @deprecated Use {@link @backstage/plugin-app-react#ThemeBlueprint} instead.
3419
- */
3420
- declare const ThemeBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
3421
- kind: "theme";
3422
- params: {
3423
- theme: AppTheme;
3424
- };
3425
- output: _backstage_frontend_plugin_api.ExtensionDataRef<AppTheme, "core.theme.theme", {}>;
3426
- inputs: {};
3427
- config: {};
3428
- configInput: {};
3429
- dataRefs: {
3430
- theme: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<AppTheme, "core.theme.theme", {}>;
3431
- };
3432
- }>;
3433
-
3434
- /**
3435
- * Creates an extension that adds translations to your app.
3436
- *
3437
- * @public
3438
- * @deprecated Use {@link @backstage/plugin-app-react#TranslationBlueprint} instead.
3439
- */
3440
- declare const TranslationBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
3441
- kind: "translation";
3442
- params: {
3443
- resource: TranslationResource | TranslationMessages;
3444
- };
3445
- output: _backstage_frontend_plugin_api.ExtensionDataRef<TranslationResource<string> | TranslationMessages<string, {
3446
- [x: string]: string;
3447
- }, boolean>, "core.translation.translation", {}>;
3448
- inputs: {};
3449
- config: {};
3450
- configInput: {};
3451
- dataRefs: {
3452
- translation: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<TranslationResource<string> | TranslationMessages<string, {
3453
- [x: string]: string;
3454
- }, boolean>, "core.translation.translation", {}>;
3455
- };
3456
- }>;
3457
-
3458
- /**
3459
- * Blueprint for creating swappable components from a SwappableComponentRef and a loader
3460
- *
3461
- * @public
3462
- * @deprecated Use {@link @backstage/plugin-app-react#SwappableComponentBlueprint} instead.
3463
- */
3464
- declare const SwappableComponentBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
3465
- kind: "component";
3466
- params: <Ref extends SwappableComponentRef<any>>(params: {
3467
- component: Ref extends SwappableComponentRef<any, infer IExternalComponentProps> ? {
3468
- ref: Ref;
3469
- } & ((props: IExternalComponentProps) => JSX.Element | null) : never;
3470
- loader: Ref extends SwappableComponentRef<infer IInnerComponentProps, any> ? (() => (props: IInnerComponentProps) => JSX.Element | null) | (() => Promise<(props: IInnerComponentProps) => JSX.Element | null>) : never;
3471
- }) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<{
3472
- component: Ref extends SwappableComponentRef<any, infer IExternalComponentProps> ? {
3473
- ref: Ref;
3474
- } & ((props: IExternalComponentProps) => JSX.Element | null) : never;
3475
- loader: Ref extends SwappableComponentRef<infer IInnerComponentProps, any> ? (() => (props: IInnerComponentProps) => JSX.Element | null) | (() => Promise<(props: IInnerComponentProps) => JSX.Element | null>) : never;
3476
- }>;
3477
- output: _backstage_frontend_plugin_api.ExtensionDataRef<{
3478
- ref: SwappableComponentRef;
3479
- loader: (() => (props: {}) => JSX.Element | null) | (() => Promise<(props: {}) => JSX.Element | null>);
3480
- }, "core.swappableComponent", {}>;
3481
- inputs: {};
3482
- config: {};
3483
- configInput: {};
3484
- dataRefs: {
3485
- component: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
3486
- ref: SwappableComponentRef;
3487
- loader: (() => (props: {}) => JSX.Element | null) | (() => Promise<(props: {}) => JSX.Element | null>);
3488
- }, "core.swappableComponent", {}>;
3489
- };
3490
- }>;
3491
-
3492
- export { AnalyticsContext, AnalyticsImplementationBlueprint, ApiBlueprint, AppRootElementBlueprint, AppRootWrapperBlueprint, ErrorDisplay, ExtensionBoundary, FeatureFlagState, IconBundleBlueprint, NavContentBlueprint, NavItemBlueprint, NotFoundErrorPage, PageBlueprint, Progress, RouterBlueprint, SessionState, SignInPageBlueprint, SwappableComponentBlueprint, ThemeBlueprint, TranslationBlueprint, alertApiRef, analyticsApiRef, appLanguageApiRef, appThemeApiRef, appTreeApiRef, atlassianAuthApiRef, bitbucketAuthApiRef, bitbucketServerAuthApiRef, configApiRef, coreExtensionData, createApiFactory, createApiRef, createExtension, createExtensionBlueprint, createExtensionBlueprintParams, createExtensionDataRef, createExtensionInput, createExternalRouteRef, createFrontendFeatureLoader, createFrontendModule, createFrontendPlugin, createRouteRef, createSubRouteRef, createSwappableComponent, createTranslationMessages, createTranslationRef, createTranslationResource, dialogApiRef, discoveryApiRef, errorApiRef, featureFlagsApiRef, fetchApiRef, githubAuthApiRef, gitlabAuthApiRef, googleAuthApiRef, iconsApiRef, identityApiRef, microsoftAuthApiRef, oauthRequestApiRef, oktaAuthApiRef, oneloginAuthApiRef, openshiftAuthApiRef, routeResolutionApiRef, storageApiRef, swappableComponentsApiRef, translationApiRef, useAnalytics, useApi, useApiHolder, useAppNode, useRouteRef, useRouteRefParams, useTranslationRef, vmwareCloudAuthApiRef, withApis };
3493
- export type { AlertApi, AlertMessage, AnalyticsApi, AnalyticsContextValue, AnalyticsEvent, AnalyticsEventAttributes, AnalyticsImplementation, AnalyticsImplementationFactory, AnalyticsTracker, AnyApiFactory, AnyApiRef, AnyExtensionDataRef, AnyRouteRefParams, ApiFactory, ApiHolder, ApiRef, ApiRefConfig, AppLanguageApi, AppNode, AppNodeEdges, AppNodeInstance, AppNodeSpec, AppTheme, AppThemeApi, AppTree, AppTreeApi, AuthProviderInfo, AuthRequestOptions, BackstageIdentityApi, BackstageIdentityResponse, BackstageUserIdentity, ConfigApi, ConfigurableExtensionDataRef, CreateExtensionBlueprintOptions, CreateExtensionOptions, CreateFrontendFeatureLoaderOptions, CreateFrontendModuleOptions, CreateSwappableComponentOptions, DialogApi, DialogApiDialog, DiscoveryApi, ErrorApi, ErrorApiError, ErrorApiErrorContext, ErrorDisplayProps, Extension, ExtensionAttachTo, ExtensionAttachToSpec, ExtensionBlueprint, ExtensionBlueprintDefineParams, ExtensionBlueprintParameters, ExtensionBlueprintParams, ExtensionBoundaryProps, ExtensionDataContainer, ExtensionDataRef, ExtensionDataRefToValue, ExtensionDataValue, ExtensionDefinition, ExtensionDefinitionAttachTo, ExtensionDefinitionParameters, ExtensionFactoryMiddleware, ExtensionInput, ExternalRouteRef, FeatureFlag, FeatureFlagConfig, FeatureFlagsApi, FeatureFlagsSaveOptions, FetchApi, FrontendFeature, FrontendFeatureLoader, FrontendModule, FrontendPlugin, FrontendPluginInfo, FrontendPluginInfoOptions, IconComponent, IconsApi, IdentityApi, NavContentComponent, NavContentComponentProps, NotFoundErrorPageProps, OAuthApi, OAuthRequestApi, OAuthRequester, OAuthRequesterOptions, OAuthScope, OpenIdConnectApi, OverridableExtensionDefinition, OverridableFrontendPlugin, PendingOAuthRequest, PluginOptions, PortableSchema, ProfileInfo, ProfileInfoApi, ProgressProps, ResolvedExtensionInput, ResolvedExtensionInputs, RouteFunc, RouteRef, RouteResolutionApi, SessionApi, SignInPageProps, StorageApi, StorageValueSnapshot, SubRouteRef, SwappableComponentRef, SwappableComponentsApi, TranslationApi, TranslationFunction, TranslationMessages, TranslationMessagesOptions, TranslationRef, TranslationRefOptions, TranslationResource, TranslationResourceOptions, TranslationSnapshot, TypesToApiRefs };
3295
+ export { AnalyticsContext, AnalyticsImplementationBlueprint, ApiBlueprint, AppRootElementBlueprint, ErrorDisplay, ExtensionBoundary, FeatureFlagState, NavItemBlueprint, NotFoundErrorPage, PageBlueprint, Progress, SessionState, alertApiRef, analyticsApiRef, appLanguageApiRef, appThemeApiRef, appTreeApiRef, atlassianAuthApiRef, bitbucketAuthApiRef, bitbucketServerAuthApiRef, configApiRef, coreExtensionData, createApiFactory, createApiRef, createExtension, createExtensionBlueprint, createExtensionBlueprintParams, createExtensionDataRef, createExtensionInput, createExternalRouteRef, createFrontendFeatureLoader, createFrontendModule, createFrontendPlugin, createRouteRef, createSubRouteRef, createSwappableComponent, createTranslationMessages, createTranslationRef, createTranslationResource, dialogApiRef, discoveryApiRef, errorApiRef, featureFlagsApiRef, fetchApiRef, githubAuthApiRef, gitlabAuthApiRef, googleAuthApiRef, iconsApiRef, identityApiRef, microsoftAuthApiRef, oauthRequestApiRef, oktaAuthApiRef, oneloginAuthApiRef, openshiftAuthApiRef, routeResolutionApiRef, storageApiRef, swappableComponentsApiRef, translationApiRef, useAnalytics, useApi, useApiHolder, useAppNode, useRouteRef, useRouteRefParams, useTranslationRef, vmwareCloudAuthApiRef, withApis };
3296
+ export type { AlertApi, AlertMessage, AnalyticsApi, AnalyticsContextValue, AnalyticsEvent, AnalyticsEventAttributes, AnalyticsImplementation, AnalyticsImplementationFactory, AnalyticsTracker, AnyApiFactory, AnyApiRef, AnyExtensionDataRef, AnyRouteRefParams, ApiFactory, ApiHolder, ApiRef, ApiRefConfig, AppLanguageApi, AppNode, AppNodeEdges, AppNodeInstance, AppNodeSpec, AppTheme, AppThemeApi, AppTree, AppTreeApi, AuthProviderInfo, AuthRequestOptions, BackstageIdentityApi, BackstageIdentityResponse, BackstageUserIdentity, ConfigApi, ConfigurableExtensionDataRef, CreateExtensionBlueprintOptions, CreateExtensionOptions, CreateFrontendFeatureLoaderOptions, CreateFrontendModuleOptions, CreateSwappableComponentOptions, DialogApi, DialogApiDialog, DiscoveryApi, ErrorApi, ErrorApiError, ErrorApiErrorContext, ErrorDisplayProps, Extension, ExtensionAttachTo, ExtensionAttachToSpec, ExtensionBlueprint, ExtensionBlueprintDefineParams, ExtensionBlueprintParameters, ExtensionBlueprintParams, ExtensionBoundaryProps, ExtensionDataContainer, ExtensionDataRef, ExtensionDataRefToValue, ExtensionDataValue, ExtensionDefinition, ExtensionDefinitionAttachTo, ExtensionDefinitionParameters, ExtensionFactoryMiddleware, ExtensionInput, ExternalRouteRef, FeatureFlag, FeatureFlagConfig, FeatureFlagsApi, FeatureFlagsSaveOptions, FetchApi, FrontendFeature, FrontendFeatureLoader, FrontendModule, FrontendPlugin, FrontendPluginInfo, FrontendPluginInfoOptions, IconComponent, IconsApi, IdentityApi, NotFoundErrorPageProps, OAuthApi, OAuthRequestApi, OAuthRequester, OAuthRequesterOptions, OAuthScope, OpenIdConnectApi, OverridableExtensionDefinition, OverridableFrontendPlugin, PendingOAuthRequest, PluginOptions, PortableSchema, ProfileInfo, ProfileInfoApi, ProgressProps, ResolvedExtensionInput, ResolvedExtensionInputs, RouteFunc, RouteRef, RouteResolutionApi, SessionApi, StorageApi, StorageValueSnapshot, SubRouteRef, SwappableComponentRef, SwappableComponentsApi, TranslationApi, TranslationFunction, TranslationMessages, TranslationMessagesOptions, TranslationRef, TranslationRefOptions, TranslationResource, TranslationResourceOptions, TranslationSnapshot, TypesToApiRefs };
package/dist/index.esm.js CHANGED
@@ -25,16 +25,8 @@ export { createApiFactory } from './apis/system/helpers.esm.js';
25
25
  export { AnalyticsImplementationBlueprint } from './blueprints/AnalyticsImplementationBlueprint.esm.js';
26
26
  export { ApiBlueprint } from './blueprints/ApiBlueprint.esm.js';
27
27
  export { AppRootElementBlueprint } from './blueprints/AppRootElementBlueprint.esm.js';
28
- export { AppRootWrapperBlueprint } from './blueprints/AppRootWrapperBlueprint.esm.js';
29
- export { IconBundleBlueprint } from './blueprints/IconBundleBlueprint.esm.js';
30
- export { NavContentBlueprint } from './blueprints/NavContentBlueprint.esm.js';
31
28
  export { NavItemBlueprint } from './blueprints/NavItemBlueprint.esm.js';
32
29
  export { PageBlueprint } from './blueprints/PageBlueprint.esm.js';
33
- export { RouterBlueprint } from './blueprints/RouterBlueprint.esm.js';
34
- export { SignInPageBlueprint } from './blueprints/SignInPageBlueprint.esm.js';
35
- export { ThemeBlueprint } from './blueprints/ThemeBlueprint.esm.js';
36
- export { TranslationBlueprint } from './blueprints/TranslationBlueprint.esm.js';
37
- export { SwappableComponentBlueprint } from './blueprints/SwappableComponentBlueprint.esm.js';
38
30
  export { ExtensionBoundary } from './components/ExtensionBoundary.esm.js';
39
31
  export { createSwappableComponent } from './components/createSwappableComponent.esm.js';
40
32
  export { useAppNode } from './components/AppNodeProvider.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,4 @@
1
+ const ID_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/i;
2
+
3
+ export { ID_PATTERN };
4
+ //# sourceMappingURL=constants.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.esm.js","sources":["../../src/wiring/constants.ts"],"sourcesContent":["/*\n * Copyright 2025 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\n// NOTE: changing any of these constants need to be reflected in\n// @backstage/backend-plugin-api/src/wiring/constants.ts as well\n\n/**\n * The pattern that IDs must match.\n *\n * @remarks\n * ids must only contain the letters `a` through `z` and digits, in groups separated by\n * dashes. Additionally, the very first character of the first group\n * must be a letter, not a digit\n *\n * @public\n */\nexport const ID_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/i;\n"],"names":[],"mappings":"AA6BO,MAAM,UAAA,GAAa;;;;"}