@backstage/frontend-plugin-api 0.9.6-next.0 → 0.10.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @backstage/frontend-plugin-api
2
2
 
3
+ ## 0.10.0-next.2
4
+
5
+ ### Minor Changes
6
+
7
+ - 8250ffe: **BREAKING**: Removed the deprecated `ExtensionOverrides` and `FrontendFeature` types.
8
+ - 0d1a397: **BREAKING**: Removed deprecated variant of `createExtensionDataRef` where the ID is passed directly.
9
+
10
+ ### Patch Changes
11
+
12
+ - 5aa7f2c: Added a new Utility API, `DialogApi`, which can be used to show dialogs in the React tree that can collect input from the user.
13
+ - e23f5e0: Added new `ExtensionMiddlewareFactory` type.
14
+ - a6cb67d: The extensions map for plugins created with `createFrontendPlugin` is now sorted alphabetically by ID in the TypeScript type.
15
+ - Updated dependencies
16
+ - @backstage/core-components@0.16.5-next.1
17
+ - @backstage/core-plugin-api@1.10.4
18
+ - @backstage/types@1.2.1
19
+ - @backstage/version-bridge@1.0.11
20
+
21
+ ## 0.9.6-next.1
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies
26
+ - @backstage/core-components@0.16.5-next.0
27
+ - @backstage/core-plugin-api@1.10.4
28
+ - @backstage/types@1.2.1
29
+ - @backstage/version-bridge@1.0.11
30
+
3
31
  ## 0.9.6-next.0
4
32
 
5
33
  ### Patch Changes
@@ -3,6 +3,7 @@ import { useAnalyticsContext } from './AnalyticsContext.esm.js';
3
3
  import '../apis/definitions/AppTreeApi.esm.js';
4
4
  import '../apis/definitions/ComponentsApi.esm.js';
5
5
  import '../apis/definitions/IconsApi.esm.js';
6
+ import '../apis/definitions/DialogApi.esm.js';
6
7
  import '../apis/definitions/RouteResolutionApi.esm.js';
7
8
  import { analyticsApiRef } from '../apis/definitions/AnalyticsApi.esm.js';
8
9
  import { useRef } from 'react';
@@ -1 +1 @@
1
- {"version":3,"file":"useAnalytics.esm.js","sources":["../../src/analytics/useAnalytics.tsx"],"sourcesContent":["/*\n * Copyright 2021 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 { useApi } from '@backstage/core-plugin-api';\nimport { useAnalyticsContext } from './AnalyticsContext';\nimport { analyticsApiRef, AnalyticsTracker, AnalyticsApi } from '../apis';\nimport { useRef } from 'react';\nimport { Tracker } from './Tracker';\n\nfunction useAnalyticsApi(): AnalyticsApi {\n try {\n return useApi(analyticsApiRef);\n } catch (error) {\n if (error.name === 'NotImplementedError') {\n return { captureEvent: () => {} };\n }\n throw error;\n }\n}\n\n/**\n * Gets a pre-configured analytics tracker.\n *\n * @public\n */\nexport function useAnalytics(): AnalyticsTracker {\n const trackerRef = useRef<Tracker | null>(null);\n const context = useAnalyticsContext();\n // Our goal is to make this API truly optional for any/all consuming code\n // (including tests). This hook runs last to ensure hook order is, as much as\n // possible, maintained.\n const analyticsApi = useAnalyticsApi();\n\n function getTracker(): Tracker {\n if (trackerRef.current === null) {\n trackerRef.current = new Tracker(analyticsApi);\n }\n return trackerRef.current;\n }\n\n const tracker = getTracker();\n // this is not ideal, but it allows to memoize the tracker\n // without explicitly set the context as dependency.\n tracker.setContext(context);\n\n return tracker;\n}\n"],"names":[],"mappings":";;;;;;;;;;AAsBA,SAAS,eAAgC,GAAA;AACvC,EAAI,IAAA;AACF,IAAA,OAAO,OAAO,eAAe,CAAA;AAAA,WACtB,KAAO,EAAA;AACd,IAAI,IAAA,KAAA,CAAM,SAAS,qBAAuB,EAAA;AACxC,MAAO,OAAA,EAAE,cAAc,MAAM;AAAA,OAAG,EAAA;AAAA;AAElC,IAAM,MAAA,KAAA;AAAA;AAEV;AAOO,SAAS,YAAiC,GAAA;AAC/C,EAAM,MAAA,UAAA,GAAa,OAAuB,IAAI,CAAA;AAC9C,EAAA,MAAM,UAAU,mBAAoB,EAAA;AAIpC,EAAA,MAAM,eAAe,eAAgB,EAAA;AAErC,EAAA,SAAS,UAAsB,GAAA;AAC7B,IAAI,IAAA,UAAA,CAAW,YAAY,IAAM,EAAA;AAC/B,MAAW,UAAA,CAAA,OAAA,GAAU,IAAI,OAAA,CAAQ,YAAY,CAAA;AAAA;AAE/C,IAAA,OAAO,UAAW,CAAA,OAAA;AAAA;AAGpB,EAAA,MAAM,UAAU,UAAW,EAAA;AAG3B,EAAA,OAAA,CAAQ,WAAW,OAAO,CAAA;AAE1B,EAAO,OAAA,OAAA;AACT;;;;"}
1
+ {"version":3,"file":"useAnalytics.esm.js","sources":["../../src/analytics/useAnalytics.tsx"],"sourcesContent":["/*\n * Copyright 2021 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 { useApi } from '@backstage/core-plugin-api';\nimport { useAnalyticsContext } from './AnalyticsContext';\nimport { analyticsApiRef, AnalyticsTracker, AnalyticsApi } from '../apis';\nimport { useRef } from 'react';\nimport { Tracker } from './Tracker';\n\nfunction useAnalyticsApi(): AnalyticsApi {\n try {\n return useApi(analyticsApiRef);\n } catch (error) {\n if (error.name === 'NotImplementedError') {\n return { captureEvent: () => {} };\n }\n throw error;\n }\n}\n\n/**\n * Gets a pre-configured analytics tracker.\n *\n * @public\n */\nexport function useAnalytics(): AnalyticsTracker {\n const trackerRef = useRef<Tracker | null>(null);\n const context = useAnalyticsContext();\n // Our goal is to make this API truly optional for any/all consuming code\n // (including tests). This hook runs last to ensure hook order is, as much as\n // possible, maintained.\n const analyticsApi = useAnalyticsApi();\n\n function getTracker(): Tracker {\n if (trackerRef.current === null) {\n trackerRef.current = new Tracker(analyticsApi);\n }\n return trackerRef.current;\n }\n\n const tracker = getTracker();\n // this is not ideal, but it allows to memoize the tracker\n // without explicitly set the context as dependency.\n tracker.setContext(context);\n\n return tracker;\n}\n"],"names":[],"mappings":";;;;;;;;;;;AAsBA,SAAS,eAAgC,GAAA;AACvC,EAAI,IAAA;AACF,IAAA,OAAO,OAAO,eAAe,CAAA;AAAA,WACtB,KAAO,EAAA;AACd,IAAI,IAAA,KAAA,CAAM,SAAS,qBAAuB,EAAA;AACxC,MAAO,OAAA,EAAE,cAAc,MAAM;AAAA,OAAG,EAAA;AAAA;AAElC,IAAM,MAAA,KAAA;AAAA;AAEV;AAOO,SAAS,YAAiC,GAAA;AAC/C,EAAM,MAAA,UAAA,GAAa,OAAuB,IAAI,CAAA;AAC9C,EAAA,MAAM,UAAU,mBAAoB,EAAA;AAIpC,EAAA,MAAM,eAAe,eAAgB,EAAA;AAErC,EAAA,SAAS,UAAsB,GAAA;AAC7B,IAAI,IAAA,UAAA,CAAW,YAAY,IAAM,EAAA;AAC/B,MAAW,UAAA,CAAA,OAAA,GAAU,IAAI,OAAA,CAAQ,YAAY,CAAA;AAAA;AAE/C,IAAA,OAAO,UAAW,CAAA,OAAA;AAAA;AAGpB,EAAA,MAAM,UAAU,UAAW,EAAA;AAG3B,EAAA,OAAA,CAAQ,WAAW,OAAO,CAAA;AAE1B,EAAO,OAAA,OAAA;AACT;;;;"}
@@ -0,0 +1,8 @@
1
+ import { createApiRef } from '@backstage/core-plugin-api';
2
+
3
+ const dialogApiRef = createApiRef({
4
+ id: "core.dialog"
5
+ });
6
+
7
+ export { dialogApiRef };
8
+ //# sourceMappingURL=DialogApi.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DialogApi.esm.js","sources":["../../../src/apis/definitions/DialogApi.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 { createApiRef } from '@backstage/core-plugin-api';\n\n/**\n * A handle for an open dialog that can be used to interact with it.\n *\n * @remarks\n *\n * Dialogs can be opened using either {@link DialogApi.show} or {@link DialogApi.showModal}.\n *\n * @public\n */\nexport interface DialogApiDialog<TResult = unknown> {\n /**\n * Closes the dialog with that provided result.\n *\n * @remarks\n *\n * If the dialog is a modal dialog a result must always be provided. If it's a regular dialog then passing a result is optional.\n */\n close(\n ...args: undefined extends TResult ? [result?: TResult] : [result: TResult]\n ): void;\n\n /**\n * Replaces the content of the dialog with the provided element or component, causing it to be rerenedered.\n */\n update(\n elementOrComponent:\n | React.JSX.Element\n | ((props: { dialog: DialogApiDialog<TResult> }) => JSX.Element),\n ): void;\n\n /**\n * Wait until the dialog is closed and return the result.\n *\n * @remarks\n *\n * If the dialog is a modal dialog a result will always be returned. If it's a regular dialog then the result may be `undefined`.\n */\n result(): Promise<TResult>;\n}\n\n/**\n * A Utility API for showing dialogs that render in the React tree and return a result.\n *\n * @public\n */\nexport interface DialogApi {\n /**\n * Opens a modal dialog and returns a handle to it.\n *\n * @remarks\n *\n * This dialog can be closed by calling the `close` method on the returned handle, optionally providing a result.\n * The dialog can also be closed by the user by clicking the backdrop or pressing the escape key.\n *\n * If the dialog is closed without a result, the result will be `undefined`.\n *\n * @example\n *\n * ### Example with inline dialog content\n * ```tsx\n * const dialog = dialogApi.show<boolean>(\n * <DialogContent>\n * <DialogTitle>Are you sure?</DialogTitle>\n * <DialogActions>\n * <Button onClick={() => dialog.close(true)}>Yes</Button>\n * <Button onClick={() => dialog.close(false)}>No</Button>\n * </DialogActions>\n * </DialogContent>\n * );\n * const result = await dialog.result();\n * ```\n *\n * @example\n *\n * ### Example with separate dialog component\n * ```tsx\n * function CustomDialog({ dialog }: { dialog: DialogApiDialog<boolean | undefined> }) {\n * return (\n * <DialogContent>\n * <DialogTitle>Are you sure?</DialogTitle>\n * <DialogActions>\n * <Button onClick={() => dialog.close(true)}>Yes</Button>\n * <Button onClick={() => dialog.close(false)}>No</Button>\n * </DialogActions>\n * </DialogContent>\n * )\n * }\n * const result = await dialogApi.show(CustomDialog).result();\n * ```\n *\n * @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.\n * @public\n */\n show<TResult = {}>(\n elementOrComponent:\n | JSX.Element\n | ((props: {\n dialog: DialogApiDialog<TResult | undefined>;\n }) => JSX.Element),\n ): DialogApiDialog<TResult | undefined>;\n\n /**\n * Opens a modal dialog and returns a handle to it.\n *\n * @remarks\n *\n * This dialog can not be closed in any other way than calling the `close` method on the returned handle and providing a result.\n *\n * @example\n *\n * ### Example with inline dialog content\n * ```tsx\n * const dialog = dialogApi.showModal<boolean>(\n * <DialogContent>\n * <DialogTitle>Are you sure?</DialogTitle>\n * <DialogActions>\n * <Button onClick={() => dialog.close(true)}>Yes</Button>\n * <Button onClick={() => dialog.close(false)}>No</Button>\n * </DialogActions>\n * </DialogContent>\n * );\n * const result = await dialog.result();\n * ```\n *\n * @example\n *\n * ### Example with separate dialog component\n * ```tsx\n * function CustomDialog({ dialog }: { dialog: DialogApiDialog<boolean> }) {\n * return (\n * <DialogContent>\n * <DialogTitle>Are you sure?</DialogTitle>\n * <DialogActions>\n * <Button onClick={() => dialog.close(true)}>Yes</Button>\n * <Button onClick={() => dialog.close(false)}>No</Button>\n * </DialogActions>\n * </DialogContent>\n * )\n * }\n * const result = await dialogApi.showModal(CustomDialog).result();\n * ```\n *\n * @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.\n * @public\n */\n showModal<TResult = {}>(\n elementOrComponent:\n | JSX.Element\n | ((props: { dialog: DialogApiDialog<TResult> }) => JSX.Element),\n ): DialogApiDialog<TResult>;\n}\n\n/**\n * The `ApiRef` of {@link DialogApi}.\n *\n * @public\n */\nexport const dialogApiRef = createApiRef<DialogApi>({\n id: 'core.dialog',\n});\n"],"names":[],"mappings":";;AA+KO,MAAM,eAAe,YAAwB,CAAA;AAAA,EAClD,EAAI,EAAA;AACN,CAAC;;;;"}
@@ -5,6 +5,7 @@ import { routableExtensionRenderedEvent } from '../core-plugin-api/src/analytics
5
5
  import '../apis/definitions/AppTreeApi.esm.js';
6
6
  import { useComponentRef } from '../apis/definitions/ComponentsApi.esm.js';
7
7
  import '../apis/definitions/IconsApi.esm.js';
8
+ import '../apis/definitions/DialogApi.esm.js';
8
9
  import '../apis/definitions/RouteResolutionApi.esm.js';
9
10
  import '../apis/definitions/AnalyticsApi.esm.js';
10
11
  import { coreComponentRefs } from './coreComponentRefs.esm.js';
@@ -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 React, {\n PropsWithChildren,\n ReactNode,\n Suspense,\n useEffect,\n lazy as reactLazy,\n} from 'react';\nimport { AnalyticsContext, useAnalytics } from '@backstage/core-plugin-api';\nimport { ErrorBoundary } from './ErrorBoundary';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker';\nimport { AppNode, useComponentRef } from '../apis';\nimport { coreComponentRefs } from './coreComponentRefs';\nimport { coreExtensionData } from '../wiring';\n\ntype RouteTrackerProps = PropsWithChildren<{\n disableTracking?: boolean;\n}>;\n\nconst RouteTracker = (props: RouteTrackerProps) => {\n const { disableTracking, 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 (disableTracking) return;\n analytics.captureEvent(routableExtensionRenderedEvent, '');\n }, [analytics, disableTracking]);\n\n return <>{children}</>;\n};\n\n/** @public */\nexport interface ExtensionBoundaryProps {\n node: AppNode;\n /**\n * This explicitly marks the extension as routable for the purpose of\n * capturing analytics events. If not provided, the extension boundary will be\n * marked as routable if it outputs a routePath.\n */\n routable?: boolean;\n children: ReactNode;\n}\n\n/** @public */\nexport function ExtensionBoundary(props: ExtensionBoundaryProps) {\n const { node, routable, children } = props;\n\n const doesOutputRoutePath = Boolean(\n node.instance?.getData(coreExtensionData.routePath),\n );\n\n const plugin = node.spec.source;\n const Progress = useComponentRef(coreComponentRefs.progress);\n const fallback = useComponentRef(coreComponentRefs.errorBoundaryFallback);\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: node.spec.source?.id ?? 'app',\n };\n\n return (\n <Suspense fallback={<Progress />}>\n <ErrorBoundary plugin={plugin} Fallback={fallback}>\n <AnalyticsContext attributes={attributes}>\n <RouteTracker disableTracking={!(routable ?? doesOutputRoutePath)}>\n {children}\n </RouteTracker>\n </AnalyticsContext>\n </ErrorBoundary>\n </Suspense>\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":";;;;;;;;;;;;;;AAmCA,MAAM,YAAA,GAAe,CAAC,KAA6B,KAAA;AACjD,EAAM,MAAA,EAAE,eAAiB,EAAA,QAAA,EAAa,GAAA,KAAA;AACtC,EAAA,MAAM,YAAY,YAAa,EAAA;AAM/B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,eAAiB,EAAA;AACrB,IAAU,SAAA,CAAA,YAAA,CAAa,gCAAgC,EAAE,CAAA;AAAA,GACxD,EAAA,CAAC,SAAW,EAAA,eAAe,CAAC,CAAA;AAE/B,EAAA,iEAAU,QAAS,CAAA;AACrB,CAAA;AAeO,SAAS,kBAAkB,KAA+B,EAAA;AAC/D,EAAA,MAAM,EAAE,IAAA,EAAM,QAAU,EAAA,QAAA,EAAa,GAAA,KAAA;AAErC,EAAA,MAAM,mBAAsB,GAAA,OAAA;AAAA,IAC1B,IAAK,CAAA,QAAA,EAAU,OAAQ,CAAA,iBAAA,CAAkB,SAAS;AAAA,GACpD;AAEA,EAAM,MAAA,MAAA,GAAS,KAAK,IAAK,CAAA,MAAA;AACzB,EAAM,MAAA,QAAA,GAAW,eAAgB,CAAA,iBAAA,CAAkB,QAAQ,CAAA;AAC3D,EAAM,MAAA,QAAA,GAAW,eAAgB,CAAA,iBAAA,CAAkB,qBAAqB,CAAA;AAGxE,EAAA,MAAM,UAAa,GAAA;AAAA,IACjB,WAAA,EAAa,KAAK,IAAK,CAAA,EAAA;AAAA,IACvB,QAAU,EAAA,IAAA,CAAK,IAAK,CAAA,MAAA,EAAQ,EAAM,IAAA;AAAA,GACpC;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,YAAS,QAAU,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAS,CAC5B,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,aAAc,EAAA,EAAA,MAAA,EAAgB,QAAU,EAAA,QAAA,EAAA,sCACtC,gBAAiB,EAAA,EAAA,UAAA,EAAA,kBACf,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAa,eAAiB,EAAA,EAAE,YAAY,mBAC1C,CAAA,EAAA,EAAA,QACH,CACF,CACF,CACF,CAAA;AAEJ;AAAA,CAGO,CAAUA,kBAAV,KAAA;AACE,EAAS,SAAAC,MAAA,CACd,SACA,MACa,EAAA;AACb,IAAA,MAAM,kBAAqB,GAAAC,IAAA;AAAA,MAAU,MACnC,QAAS,CAAA,IAAA,CAAK,cAAY,EAAE,OAAA,EAAS,MAAM,OAAA,EAAU,CAAA;AAAA,KACvD;AACA,IAAA,2CACGF,kBAAA,EAAA,EAAkB,MAAM,OACvB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,wBAAmB,CACtB,CAAA;AAAA;AAVG,EAAAA,kBAAS,CAAA,IAAA,GAAAC,MAAA;AAcT,EAAS,SAAA,aAAA,CACd,SACA,MACgC,EAAA;AAChC,IAAA,MAAM,kBAAqB,GAAAC,IAAA;AAAA,MAAU,MACnC,QAAS,CAAA,IAAA,CAAK,gBAAc,EAAE,OAAA,EAAS,WAAY,CAAA;AAAA,KACrD;AAEA,IAAO,OAAA,CAAC,KACN,qBAAA,KAAA,CAAA,aAAA,CAACF,kBAAA,EAAA,EAAkB,IAAM,EAAA,OAAA,EAAA,kBACtB,KAAA,CAAA,aAAA,CAAA,kBAAA,EAAA,EAAoB,GAAG,KAAA,EAAO,CACjC,CAAA;AAAA;AAXG,EAAAA,kBAAS,CAAA,aAAA,GAAA,aAAA;AAAA,CAfD,EAAA,iBAAA,KAAA,iBAAA,GAAA,EAAA,CAAA,CAAA;;;;"}
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 React, {\n PropsWithChildren,\n ReactNode,\n Suspense,\n useEffect,\n lazy as reactLazy,\n} from 'react';\nimport { AnalyticsContext, useAnalytics } from '@backstage/core-plugin-api';\nimport { ErrorBoundary } from './ErrorBoundary';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker';\nimport { AppNode, useComponentRef } from '../apis';\nimport { coreComponentRefs } from './coreComponentRefs';\nimport { coreExtensionData } from '../wiring';\n\ntype RouteTrackerProps = PropsWithChildren<{\n disableTracking?: boolean;\n}>;\n\nconst RouteTracker = (props: RouteTrackerProps) => {\n const { disableTracking, 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 (disableTracking) return;\n analytics.captureEvent(routableExtensionRenderedEvent, '');\n }, [analytics, disableTracking]);\n\n return <>{children}</>;\n};\n\n/** @public */\nexport interface ExtensionBoundaryProps {\n node: AppNode;\n /**\n * This explicitly marks the extension as routable for the purpose of\n * capturing analytics events. If not provided, the extension boundary will be\n * marked as routable if it outputs a routePath.\n */\n routable?: boolean;\n children: ReactNode;\n}\n\n/** @public */\nexport function ExtensionBoundary(props: ExtensionBoundaryProps) {\n const { node, routable, children } = props;\n\n const doesOutputRoutePath = Boolean(\n node.instance?.getData(coreExtensionData.routePath),\n );\n\n const plugin = node.spec.source;\n const Progress = useComponentRef(coreComponentRefs.progress);\n const fallback = useComponentRef(coreComponentRefs.errorBoundaryFallback);\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: node.spec.source?.id ?? 'app',\n };\n\n return (\n <Suspense fallback={<Progress />}>\n <ErrorBoundary plugin={plugin} Fallback={fallback}>\n <AnalyticsContext attributes={attributes}>\n <RouteTracker disableTracking={!(routable ?? doesOutputRoutePath)}>\n {children}\n </RouteTracker>\n </AnalyticsContext>\n </ErrorBoundary>\n </Suspense>\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":";;;;;;;;;;;;;;;AAmCA,MAAM,YAAA,GAAe,CAAC,KAA6B,KAAA;AACjD,EAAM,MAAA,EAAE,eAAiB,EAAA,QAAA,EAAa,GAAA,KAAA;AACtC,EAAA,MAAM,YAAY,YAAa,EAAA;AAM/B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,eAAiB,EAAA;AACrB,IAAU,SAAA,CAAA,YAAA,CAAa,gCAAgC,EAAE,CAAA;AAAA,GACxD,EAAA,CAAC,SAAW,EAAA,eAAe,CAAC,CAAA;AAE/B,EAAA,iEAAU,QAAS,CAAA;AACrB,CAAA;AAeO,SAAS,kBAAkB,KAA+B,EAAA;AAC/D,EAAA,MAAM,EAAE,IAAA,EAAM,QAAU,EAAA,QAAA,EAAa,GAAA,KAAA;AAErC,EAAA,MAAM,mBAAsB,GAAA,OAAA;AAAA,IAC1B,IAAK,CAAA,QAAA,EAAU,OAAQ,CAAA,iBAAA,CAAkB,SAAS;AAAA,GACpD;AAEA,EAAM,MAAA,MAAA,GAAS,KAAK,IAAK,CAAA,MAAA;AACzB,EAAM,MAAA,QAAA,GAAW,eAAgB,CAAA,iBAAA,CAAkB,QAAQ,CAAA;AAC3D,EAAM,MAAA,QAAA,GAAW,eAAgB,CAAA,iBAAA,CAAkB,qBAAqB,CAAA;AAGxE,EAAA,MAAM,UAAa,GAAA;AAAA,IACjB,WAAA,EAAa,KAAK,IAAK,CAAA,EAAA;AAAA,IACvB,QAAU,EAAA,IAAA,CAAK,IAAK,CAAA,MAAA,EAAQ,EAAM,IAAA;AAAA,GACpC;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,YAAS,QAAU,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAS,CAC5B,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,aAAc,EAAA,EAAA,MAAA,EAAgB,QAAU,EAAA,QAAA,EAAA,sCACtC,gBAAiB,EAAA,EAAA,UAAA,EAAA,kBACf,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAa,eAAiB,EAAA,EAAE,YAAY,mBAC1C,CAAA,EAAA,EAAA,QACH,CACF,CACF,CACF,CAAA;AAEJ;AAAA,CAGO,CAAUA,kBAAV,KAAA;AACE,EAAS,SAAAC,MAAA,CACd,SACA,MACa,EAAA;AACb,IAAA,MAAM,kBAAqB,GAAAC,IAAA;AAAA,MAAU,MACnC,QAAS,CAAA,IAAA,CAAK,cAAY,EAAE,OAAA,EAAS,MAAM,OAAA,EAAU,CAAA;AAAA,KACvD;AACA,IAAA,2CACGF,kBAAA,EAAA,EAAkB,MAAM,OACvB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,wBAAmB,CACtB,CAAA;AAAA;AAVG,EAAAA,kBAAS,CAAA,IAAA,GAAAC,MAAA;AAcT,EAAS,SAAA,aAAA,CACd,SACA,MACgC,EAAA;AAChC,IAAA,MAAM,kBAAqB,GAAAC,IAAA;AAAA,MAAU,MACnC,QAAS,CAAA,IAAA,CAAK,gBAAc,EAAE,OAAA,EAAS,WAAY,CAAA;AAAA,KACrD;AAEA,IAAO,OAAA,CAAC,KACN,qBAAA,KAAA,CAAA,aAAA,CAACF,kBAAA,EAAA,EAAkB,IAAM,EAAA,OAAA,EAAA,kBACtB,KAAA,CAAA,aAAA,CAAA,kBAAA,EAAA,EAAoB,GAAG,KAAA,EAAO,CACjC,CAAA;AAAA;AAXG,EAAAA,kBAAS,CAAA,aAAA,GAAA,aAAA;AAAA,CAfD,EAAA,iBAAA,KAAA,iBAAA,GAAA,EAAA,CAAA,CAAA;;;;"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createExtensionDataContainer.esm.js","sources":["../../../../../frontend-internal/src/wiring/createExtensionDataContainer.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AnyExtensionDataRef,\n ExtensionDataContainer,\n ExtensionDataRef,\n ExtensionDataValue,\n} from '@backstage/frontend-plugin-api';\n\nexport function createExtensionDataContainer<UData extends AnyExtensionDataRef>(\n values: Iterable<\n UData extends ExtensionDataRef<infer IData, infer IId>\n ? ExtensionDataValue<IData, IId>\n : never\n >,\n declaredRefs?: ExtensionDataRef<any, any, any>[],\n): ExtensionDataContainer<UData> {\n const container = new Map<string, ExtensionDataValue<any, any>>();\n const verifyRefs =\n declaredRefs && new Map(declaredRefs.map(ref => [ref.id, ref]));\n\n for (const output of values) {\n if (verifyRefs) {\n if (!verifyRefs.delete(output.id)) {\n throw new Error(\n `extension data '${output.id}' was provided but not declared`,\n );\n }\n }\n container.set(output.id, output);\n }\n\n const remainingRefs =\n verifyRefs &&\n Array.from(verifyRefs.values()).filter(ref => !ref.config.optional);\n if (remainingRefs && remainingRefs.length > 0) {\n throw new Error(\n `missing required extension data value(s) '${remainingRefs\n .map(ref => ref.id)\n .join(', ')}'`,\n );\n }\n\n return {\n get(ref) {\n return container.get(ref.id)?.value;\n },\n [Symbol.iterator]() {\n return container.values();\n },\n } as ExtensionDataContainer<UData>;\n}\n"],"names":[],"mappings":"AAuBgB,SAAA,4BAAA,CACd,QAKA,YAC+B,EAAA;AAC/B,EAAM,MAAA,SAAA,uBAAgB,GAA0C,EAAA;AAChE,EAAA,MAAM,UACJ,GAAA,YAAA,IAAgB,IAAI,GAAA,CAAI,YAAa,CAAA,GAAA,CAAI,CAAO,GAAA,KAAA,CAAC,GAAI,CAAA,EAAA,EAAI,GAAG,CAAC,CAAC,CAAA;AAEhE,EAAA,KAAA,MAAW,UAAU,MAAQ,EAAA;AAC3B,IAAA,IAAI,UAAY,EAAA;AACd,MAAA,IAAI,CAAC,UAAA,CAAW,MAAO,CAAA,MAAA,CAAO,EAAE,CAAG,EAAA;AACjC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,gBAAA,EAAmB,OAAO,EAAE,CAAA,+BAAA;AAAA,SAC9B;AAAA;AACF;AAEF,IAAU,SAAA,CAAA,GAAA,CAAI,MAAO,CAAA,EAAA,EAAI,MAAM,CAAA;AAAA;AAGjC,EAAA,MAAM,aACJ,GAAA,UAAA,IACA,KAAM,CAAA,IAAA,CAAK,UAAW,CAAA,MAAA,EAAQ,CAAA,CAAE,MAAO,CAAA,CAAA,GAAA,KAAO,CAAC,GAAA,CAAI,OAAO,QAAQ,CAAA;AACpE,EAAI,IAAA,aAAA,IAAiB,aAAc,CAAA,MAAA,GAAS,CAAG,EAAA;AAC7C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,0CAAA,EAA6C,cAC1C,GAAI,CAAA,CAAA,GAAA,KAAO,IAAI,EAAE,CAAA,CACjB,IAAK,CAAA,IAAI,CAAC,CAAA,CAAA;AAAA,KACf;AAAA;AAGF,EAAO,OAAA;AAAA,IACL,IAAI,GAAK,EAAA;AACP,MAAA,OAAO,SAAU,CAAA,GAAA,CAAI,GAAI,CAAA,EAAE,CAAG,EAAA,KAAA;AAAA,KAChC;AAAA,IACA,CAAC,MAAO,CAAA,QAAQ,CAAI,GAAA;AAClB,MAAA,OAAO,UAAU,MAAO,EAAA;AAAA;AAC1B,GACF;AACF;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- /// <reference types="react" />
2
- import * as React from 'react';
1
+ import * as React$1 from 'react';
3
2
  import React__default, { ReactNode, JSX as JSX$1, ComponentType, PropsWithChildren } from 'react';
4
3
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
5
4
  import { ApiHolder, ApiRef, AnyApiFactory, IconComponent as IconComponent$1, SignInPageProps, AppTheme } from '@backstage/core-plugin-api';
@@ -243,11 +242,6 @@ interface ConfigurableExtensionDataRef<TData, TId extends string, TConfig extend
243
242
  }>;
244
243
  (t: TData): ExtensionDataValue<TData, TId>;
245
244
  }
246
- /**
247
- * @public
248
- * @deprecated Use the following form instead: `createExtensionDataRef<Type>().with({ id: 'core.foo' })`
249
- */
250
- declare function createExtensionDataRef<TData>(id: string): ConfigurableExtensionDataRef<TData, string>;
251
245
  /** @public */
252
246
  declare function createExtensionDataRef<TData>(): {
253
247
  with<TId extends string>(options: {
@@ -322,10 +316,35 @@ type ResolveInputValueOverrides<TInputs extends {
322
316
  }> ? ISingleton extends true ? Iterable<ExtensionDataRefToValue<IDataRefs>> : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>> : never;
323
317
  }>;
324
318
 
319
+ /**
320
+ * Feature flag configuration.
321
+ *
322
+ * @public
323
+ */
324
+ type FeatureFlagConfig = {
325
+ /** Feature flag name */
326
+ name: string;
327
+ };
328
+ /** @public */
329
+ type AnyRoutes = {
330
+ [name in string]: RouteRef | SubRouteRef;
331
+ };
332
+ /** @public */
333
+ type AnyExternalRoutes = {
334
+ [name in string]: ExternalRouteRef;
335
+ };
325
336
  /** @public */
326
337
  type ExtensionDataContainer<UExtensionData extends AnyExtensionDataRef> = Iterable<UExtensionData extends ExtensionDataRef<infer IData, infer IId, infer IConfig> ? IConfig['optional'] extends true ? never : ExtensionDataValue<IData, IId> : never> & {
327
338
  get<TId extends UExtensionData['id']>(ref: ExtensionDataRef<any, TId, any>): UExtensionData extends ExtensionDataRef<infer IData, TId, infer IConfig> ? IConfig['optional'] extends true ? IData | undefined : IData : never;
328
339
  };
340
+ /** @public */
341
+ type ExtensionFactoryMiddleware = (originalFactory: (contextOverrides?: {
342
+ config?: JsonObject;
343
+ }) => ExtensionDataContainer<AnyExtensionDataRef>, context: {
344
+ node: AppNode;
345
+ apis: ApiHolder;
346
+ config?: JsonObject;
347
+ }) => Iterable<ExtensionDataValue<any, any>>;
329
348
 
330
349
  /**
331
350
  * Convert a single extension input into a matching resolved input.
@@ -344,9 +363,9 @@ type ResolvedExtensionInputs<TInputs extends {
344
363
  [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton'] ? Array<Expand<ResolvedExtensionInput<TInputs[InputName]>>> : false extends TInputs[InputName]['config']['optional'] ? Expand<ResolvedExtensionInput<TInputs[InputName]>> : Expand<ResolvedExtensionInput<TInputs[InputName]> | undefined>;
345
364
  };
346
365
  type ToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
347
- type PopUnion<U> = ToIntersection<U extends any ? () => U : never> extends () => infer R ? [rest: Exclude<U, R>, next: R] : undefined;
366
+ type PopUnion$1<U> = ToIntersection<U extends any ? () => U : never> extends () => infer R ? [rest: Exclude<U, R>, next: R] : undefined;
348
367
  /** @ignore */
349
- type JoinStringUnion<U, TDiv extends string = ', ', TResult extends string = ''> = PopUnion<U> extends [infer IRest extends string, infer INext extends string] ? TResult extends '' ? JoinStringUnion<IRest, TDiv, INext> : JoinStringUnion<IRest, TDiv, `${TResult}${TDiv}${INext}`> : TResult;
368
+ type JoinStringUnion<U, TDiv extends string = ', ', TResult extends string = ''> = PopUnion$1<U> extends [infer IRest extends string, infer INext extends string] ? TResult extends '' ? JoinStringUnion<IRest, TDiv, INext> : JoinStringUnion<IRest, TDiv, `${TResult}${TDiv}${INext}`> : TResult;
350
369
  /** @ignore */
351
370
  type VerifyExtensionFactoryOutput<UDeclaredOutput extends AnyExtensionDataRef, UFactoryOutput extends ExtensionDataValue<any, any>> = (UDeclaredOutput extends any ? UDeclaredOutput['config']['optional'] extends true ? never : UDeclaredOutput['id'] : never) extends infer IRequiredOutputIds ? [IRequiredOutputIds] extends [UFactoryOutput['id']] ? [UFactoryOutput['id']] extends [UDeclaredOutput['id']] ? {} : `Error: The extension factory has undeclared output(s): ${JoinStringUnion<Exclude<UFactoryOutput['id'], UDeclaredOutput['id']>>}` : `Error: The extension factory is missing the following output(s): ${JoinStringUnion<Exclude<IRequiredOutputIds, UFactoryOutput['id']>>}` : never;
352
371
  /** @public */
@@ -496,32 +515,41 @@ type ResolveExtensionId<TExtension extends ExtensionDefinition, TNamespace exten
496
515
  name: infer IName extends string | undefined;
497
516
  }> ? [string] extends [IKind | IName] ? never : (undefined extends IName ? TNamespace : `${TNamespace}/${IName}`) extends infer INamePart extends string ? IKind extends string ? `${IKind}:${INamePart}` : INamePart : never : never;
498
517
 
499
- /**
500
- * Feature flag configuration.
501
- *
502
- * @public
503
- */
504
- type FeatureFlagConfig = {
505
- /** Feature flag name */
506
- name: string;
507
- };
508
- /** @public */
509
- type AnyRoutes = {
510
- [name in string]: RouteRef | SubRouteRef;
511
- };
512
- /** @public */
513
- type AnyExternalRoutes = {
514
- [name in string]: ExternalRouteRef;
515
- };
516
- /** @public */
517
- interface ExtensionOverrides {
518
- readonly $$type: '@backstage/ExtensionOverrides';
519
- }
520
- /**
521
- * @public
522
- * @deprecated import from {@link @backstage/frontend-app-api#FrontendFeature} instead
523
- */
524
- type FrontendFeature = FrontendPlugin | ExtensionOverrides;
518
+ type CompareChars<A extends string, B extends string> = [A, B] extends [
519
+ `${infer IAHead}${infer IARest}`,
520
+ `${infer IBHead}${infer IBRest}`
521
+ ] ? IAHead extends IBHead ? IBRest extends '' ? IARest extends '' ? 'eq' : 'gt' : IARest extends '' ? 'lt' : CompareChars<IARest, IBRest> : `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz` extends `${string}${IAHead}${string}${IBHead}${string}` ? 'lt' : 'gt' : 'eq';
522
+ type CompareStrings<A extends string | undefined, B extends string | undefined> = A extends B ? 'eq' : A extends undefined ? 'lt' : B extends undefined ? 'gt' : CompareChars<A & string, B & string>;
523
+ type CompareExtensions<A extends ExtensionDefinition, B extends ExtensionDefinition> = CompareStrings<A['T']['kind'], B['T']['kind']> extends 'eq' ? CompareStrings<A['T']['name'], B['T']['name']> : CompareStrings<A['T']['kind'], B['T']['kind']>;
524
+ type SortExtensionsInner<TPivot extends ExtensionDefinition, TRest extends readonly ExtensionDefinition[], TLow extends readonly ExtensionDefinition[], THigh extends readonly ExtensionDefinition[]> = TRest extends [
525
+ infer IHead extends ExtensionDefinition,
526
+ ...infer IRest extends readonly ExtensionDefinition[]
527
+ ] ? CompareExtensions<IHead, TPivot> extends 'lt' ? SortExtensionsInner<TPivot, IRest, [...TLow, IHead], THigh> : SortExtensionsInner<TPivot, IRest, TLow, [...THigh, IHead]> : [low: TLow, high: THigh];
528
+ type SortExtensions<T extends readonly ExtensionDefinition[]> = T extends [
529
+ infer IPivot extends ExtensionDefinition,
530
+ ...infer IRest extends readonly ExtensionDefinition[]
531
+ ] ? SortExtensionsInner<IPivot, IRest, [], []> extends [
532
+ low: infer ILow extends readonly ExtensionDefinition[],
533
+ high: infer IHigh extends readonly ExtensionDefinition[]
534
+ ] ? [...SortExtensions<ILow>, IPivot, ...SortExtensions<IHigh>] : 'invalid SortExtensionsInner' : [];
535
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
536
+ type PopUnion<U> = UnionToIntersection<U extends any ? () => U : never> extends () => infer R ? [next: R, rest: Exclude<U, R>] : undefined;
537
+ type UnionToArray<U, T = U, TResult extends T[] = []> = PopUnion<U> extends [
538
+ next: infer INext extends T,
539
+ rest: infer IRest extends T
540
+ ] ? UnionToArray<IRest, T, [INext, ...TResult]> : TResult;
541
+ type ExtensionArrayToMap<T extends ExtensionDefinition[], TId extends string, TOut extends {
542
+ [KId in string]: ExtensionDefinition;
543
+ } = {}> = T extends [
544
+ infer IHead extends ExtensionDefinition,
545
+ ...infer IRest extends ExtensionDefinition[]
546
+ ] ? ExtensionArrayToMap<IRest, TId, TOut & {
547
+ [K in ResolveExtensionId<IHead, TId>]: IHead;
548
+ }> : TOut extends infer O ? {
549
+ [K in keyof O]: O[K];
550
+ } : never;
551
+ /** @ignore */
552
+ type MakeSortedExtensionsMap<UExtensions extends ExtensionDefinition, TId extends string> = ExtensionArrayToMap<SortExtensions<UnionToArray<UExtensions>>, TId>;
525
553
 
526
554
  /** @public */
527
555
  interface FrontendPlugin<TRoutes extends AnyRoutes = AnyRoutes, TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, TExtensionMap extends {
@@ -547,9 +575,7 @@ interface PluginOptions<TId extends string, TRoutes extends AnyRoutes, TExternal
547
575
  featureFlags?: FeatureFlagConfig[];
548
576
  }
549
577
  /** @public */
550
- declare function createFrontendPlugin<TId extends string, TRoutes extends AnyRoutes = {}, TExternalRoutes extends AnyExternalRoutes = {}, TExtensions extends readonly ExtensionDefinition[] = []>(options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>): FrontendPlugin<TRoutes, TExternalRoutes, {
551
- [KExtension in TExtensions[number] as ResolveExtensionId<KExtension, TId>]: KExtension;
552
- }>;
578
+ declare function createFrontendPlugin<TId extends string, TRoutes extends AnyRoutes = {}, TExternalRoutes extends AnyExternalRoutes = {}, TExtensions extends readonly ExtensionDefinition[] = []>(options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>): FrontendPlugin<TRoutes, TExternalRoutes, MakeSortedExtensionsMap<TExtensions[number], TId>>;
553
579
 
554
580
  /** @public */
555
581
  interface CreateFrontendModuleOptions<TPluginId extends string, TExtensions extends readonly ExtensionDefinition[]> {
@@ -925,6 +951,150 @@ interface IconsApi {
925
951
  */
926
952
  declare const iconsApiRef: _backstage_core_plugin_api.ApiRef<IconsApi>;
927
953
 
954
+ /**
955
+ * A handle for an open dialog that can be used to interact with it.
956
+ *
957
+ * @remarks
958
+ *
959
+ * Dialogs can be opened using either {@link DialogApi.show} or {@link DialogApi.showModal}.
960
+ *
961
+ * @public
962
+ */
963
+ interface DialogApiDialog<TResult = unknown> {
964
+ /**
965
+ * Closes the dialog with that provided result.
966
+ *
967
+ * @remarks
968
+ *
969
+ * If the dialog is a modal dialog a result must always be provided. If it's a regular dialog then passing a result is optional.
970
+ */
971
+ close(...args: undefined extends TResult ? [result?: TResult] : [result: TResult]): void;
972
+ /**
973
+ * Replaces the content of the dialog with the provided element or component, causing it to be rerenedered.
974
+ */
975
+ update(elementOrComponent: React.JSX.Element | ((props: {
976
+ dialog: DialogApiDialog<TResult>;
977
+ }) => JSX.Element)): void;
978
+ /**
979
+ * Wait until the dialog is closed and return the result.
980
+ *
981
+ * @remarks
982
+ *
983
+ * If the dialog is a modal dialog a result will always be returned. If it's a regular dialog then the result may be `undefined`.
984
+ */
985
+ result(): Promise<TResult>;
986
+ }
987
+ /**
988
+ * A Utility API for showing dialogs that render in the React tree and return a result.
989
+ *
990
+ * @public
991
+ */
992
+ interface DialogApi {
993
+ /**
994
+ * Opens a modal dialog and returns a handle to it.
995
+ *
996
+ * @remarks
997
+ *
998
+ * This dialog can be closed by calling the `close` method on the returned handle, optionally providing a result.
999
+ * The dialog can also be closed by the user by clicking the backdrop or pressing the escape key.
1000
+ *
1001
+ * If the dialog is closed without a result, the result will be `undefined`.
1002
+ *
1003
+ * @example
1004
+ *
1005
+ * ### Example with inline dialog content
1006
+ * ```tsx
1007
+ * const dialog = dialogApi.show<boolean>(
1008
+ * <DialogContent>
1009
+ * <DialogTitle>Are you sure?</DialogTitle>
1010
+ * <DialogActions>
1011
+ * <Button onClick={() => dialog.close(true)}>Yes</Button>
1012
+ * <Button onClick={() => dialog.close(false)}>No</Button>
1013
+ * </DialogActions>
1014
+ * </DialogContent>
1015
+ * );
1016
+ * const result = await dialog.result();
1017
+ * ```
1018
+ *
1019
+ * @example
1020
+ *
1021
+ * ### Example with separate dialog component
1022
+ * ```tsx
1023
+ * function CustomDialog({ dialog }: { dialog: DialogApiDialog<boolean | undefined> }) {
1024
+ * return (
1025
+ * <DialogContent>
1026
+ * <DialogTitle>Are you sure?</DialogTitle>
1027
+ * <DialogActions>
1028
+ * <Button onClick={() => dialog.close(true)}>Yes</Button>
1029
+ * <Button onClick={() => dialog.close(false)}>No</Button>
1030
+ * </DialogActions>
1031
+ * </DialogContent>
1032
+ * )
1033
+ * }
1034
+ * const result = await dialogApi.show(CustomDialog).result();
1035
+ * ```
1036
+ *
1037
+ * @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.
1038
+ * @public
1039
+ */
1040
+ show<TResult = {}>(elementOrComponent: JSX.Element | ((props: {
1041
+ dialog: DialogApiDialog<TResult | undefined>;
1042
+ }) => JSX.Element)): DialogApiDialog<TResult | undefined>;
1043
+ /**
1044
+ * Opens a modal dialog and returns a handle to it.
1045
+ *
1046
+ * @remarks
1047
+ *
1048
+ * This dialog can not be closed in any other way than calling the `close` method on the returned handle and providing a result.
1049
+ *
1050
+ * @example
1051
+ *
1052
+ * ### Example with inline dialog content
1053
+ * ```tsx
1054
+ * const dialog = dialogApi.showModal<boolean>(
1055
+ * <DialogContent>
1056
+ * <DialogTitle>Are you sure?</DialogTitle>
1057
+ * <DialogActions>
1058
+ * <Button onClick={() => dialog.close(true)}>Yes</Button>
1059
+ * <Button onClick={() => dialog.close(false)}>No</Button>
1060
+ * </DialogActions>
1061
+ * </DialogContent>
1062
+ * );
1063
+ * const result = await dialog.result();
1064
+ * ```
1065
+ *
1066
+ * @example
1067
+ *
1068
+ * ### Example with separate dialog component
1069
+ * ```tsx
1070
+ * function CustomDialog({ dialog }: { dialog: DialogApiDialog<boolean> }) {
1071
+ * return (
1072
+ * <DialogContent>
1073
+ * <DialogTitle>Are you sure?</DialogTitle>
1074
+ * <DialogActions>
1075
+ * <Button onClick={() => dialog.close(true)}>Yes</Button>
1076
+ * <Button onClick={() => dialog.close(false)}>No</Button>
1077
+ * </DialogActions>
1078
+ * </DialogContent>
1079
+ * )
1080
+ * }
1081
+ * const result = await dialogApi.showModal(CustomDialog).result();
1082
+ * ```
1083
+ *
1084
+ * @param elementOrComponent - The element or component to render in the dialog. If a component is provided, it will be provided with a `dialog` prop that contains the dialog handle.
1085
+ * @public
1086
+ */
1087
+ showModal<TResult = {}>(elementOrComponent: JSX.Element | ((props: {
1088
+ dialog: DialogApiDialog<TResult>;
1089
+ }) => JSX.Element)): DialogApiDialog<TResult>;
1090
+ }
1091
+ /**
1092
+ * The `ApiRef` of {@link DialogApi}.
1093
+ *
1094
+ * @public
1095
+ */
1096
+ declare const dialogApiRef: _backstage_core_plugin_api.ApiRef<DialogApi>;
1097
+
928
1098
  /**
929
1099
  * TS magic for handling route parameters.
930
1100
  *
@@ -1100,7 +1270,7 @@ declare const AppRootElementBlueprint: ExtensionBlueprint<{
1100
1270
  params: {
1101
1271
  element: JSX.Element | (() => JSX.Element);
1102
1272
  };
1103
- output: ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
1273
+ output: ConfigurableExtensionDataRef<React$1.JSX.Element, "core.reactElement", {}>;
1104
1274
  inputs: {};
1105
1275
  config: {};
1106
1276
  configInput: {};
@@ -1121,14 +1291,14 @@ declare const AppRootWrapperBlueprint: ExtensionBlueprint<{
1121
1291
  Component: ComponentType<PropsWithChildren<{}>>;
1122
1292
  };
1123
1293
  output: ConfigurableExtensionDataRef<React__default.ComponentType<{
1124
- children?: React__default.ReactNode;
1294
+ children?: React__default.ReactNode | undefined;
1125
1295
  }>, "app.root.wrapper", {}>;
1126
1296
  inputs: {};
1127
1297
  config: {};
1128
1298
  configInput: {};
1129
1299
  dataRefs: {
1130
1300
  component: ConfigurableExtensionDataRef<React__default.ComponentType<{
1131
- children?: React__default.ReactNode;
1301
+ children?: React__default.ReactNode | undefined;
1132
1302
  }>, "app.root.wrapper", {}>;
1133
1303
  };
1134
1304
  }>;
@@ -1138,9 +1308,7 @@ declare const IconBundleBlueprint: ExtensionBlueprint<{
1138
1308
  kind: "icon-bundle";
1139
1309
  name: undefined;
1140
1310
  params: {
1141
- icons: {
1142
- [x: string]: IconComponent;
1143
- };
1311
+ icons: { [key in string]: IconComponent; };
1144
1312
  };
1145
1313
  output: ConfigurableExtensionDataRef<{
1146
1314
  [x: string]: IconComponent;
@@ -1198,16 +1366,16 @@ declare const NavLogoBlueprint: ExtensionBlueprint<{
1198
1366
  logoFull: JSX.Element;
1199
1367
  };
1200
1368
  output: ConfigurableExtensionDataRef<{
1201
- logoIcon?: JSX.Element | undefined;
1202
- logoFull?: JSX.Element | undefined;
1369
+ logoIcon?: JSX.Element;
1370
+ logoFull?: JSX.Element;
1203
1371
  }, "core.nav-logo.logo-elements", {}>;
1204
1372
  inputs: {};
1205
1373
  config: {};
1206
1374
  configInput: {};
1207
1375
  dataRefs: {
1208
1376
  logoElements: ConfigurableExtensionDataRef<{
1209
- logoIcon?: JSX.Element | undefined;
1210
- logoFull?: JSX.Element | undefined;
1377
+ logoIcon?: JSX.Element;
1378
+ logoFull?: JSX.Element;
1211
1379
  }, "core.nav-logo.logo-elements", {}>;
1212
1380
  };
1213
1381
  }>;
@@ -1223,9 +1391,9 @@ declare const PageBlueprint: ExtensionBlueprint<{
1223
1391
  params: {
1224
1392
  defaultPath: string;
1225
1393
  loader: () => Promise<JSX.Element>;
1226
- routeRef?: RouteRef<AnyRouteRefParams> | undefined;
1394
+ routeRef?: RouteRef;
1227
1395
  };
1228
- output: ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | ConfigurableExtensionDataRef<string, "core.routing.path", {}> | ConfigurableExtensionDataRef<RouteRef<AnyRouteRefParams>, "core.routing.ref", {
1396
+ output: ConfigurableExtensionDataRef<React$1.JSX.Element, "core.reactElement", {}> | ConfigurableExtensionDataRef<string, "core.routing.path", {}> | ConfigurableExtensionDataRef<RouteRef<AnyRouteRefParams>, "core.routing.ref", {
1229
1397
  optional: true;
1230
1398
  }>;
1231
1399
  inputs: {};
@@ -1246,14 +1414,14 @@ declare const RouterBlueprint: ExtensionBlueprint<{
1246
1414
  Component: ComponentType<PropsWithChildren<{}>>;
1247
1415
  };
1248
1416
  output: ConfigurableExtensionDataRef<ComponentType<{
1249
- children?: React.ReactNode;
1417
+ children?: React$1.ReactNode | undefined;
1250
1418
  }>, "app.router.wrapper", {}>;
1251
1419
  inputs: {};
1252
1420
  config: {};
1253
1421
  configInput: {};
1254
1422
  dataRefs: {
1255
1423
  component: ConfigurableExtensionDataRef<ComponentType<{
1256
- children?: React.ReactNode;
1424
+ children?: React$1.ReactNode | undefined;
1257
1425
  }>, "app.router.wrapper", {}>;
1258
1426
  };
1259
1427
  }>;
@@ -1357,4 +1525,4 @@ declare namespace createComponentExtension {
1357
1525
  }, "core.component.component", {}>;
1358
1526
  }
1359
1527
 
1360
- export { type AnalyticsApi, AnalyticsContext, type AnalyticsContextValue, type AnalyticsEvent, type AnalyticsEventAttributes, type AnalyticsTracker, type AnyExtensionDataRef, type AnyExternalRoutes, type AnyRouteRefParams, type AnyRoutes, ApiBlueprint, type AppNode, type AppNodeEdges, type AppNodeInstance, type AppNodeSpec, AppRootElementBlueprint, AppRootWrapperBlueprint, type AppTree, type AppTreeApi, type CommonAnalyticsContext, type ComponentRef, type ComponentsApi, type ConfigurableExtensionDataRef, type CoreErrorBoundaryFallbackProps, type CoreNotFoundErrorPageProps, type CoreProgressProps, type CreateExtensionBlueprintOptions, type CreateExtensionOptions, type CreateFrontendModuleOptions, type Extension, type ExtensionAttachToSpec, type ExtensionBlueprint, type ExtensionBlueprintParameters, ExtensionBoundary, type ExtensionBoundaryProps, type ExtensionDataContainer, type ExtensionDataRef, type ExtensionDataRefToValue, type ExtensionDataValue, type ExtensionDefinition, type ExtensionDefinitionParameters, type ExtensionInput, type ExtensionOverrides, type ExternalRouteRef, type FeatureFlagConfig, type FrontendFeature, type FrontendModule, type FrontendPlugin, IconBundleBlueprint, type IconComponent, type IconsApi, NavItemBlueprint, NavLogoBlueprint, PageBlueprint, type PluginOptions, type PortableSchema, type ResolveInputValueOverrides, type ResolvedExtensionInput, type ResolvedExtensionInputs, type RouteFunc, type RouteRef, type RouteResolutionApi, type RouteResolutionApiResolveOptions, RouterBlueprint, SignInPageBlueprint, type SubRouteRef, ThemeBlueprint, TranslationBlueprint, analyticsApiRef, appTreeApiRef, componentsApiRef, coreComponentRefs, coreExtensionData, createComponentExtension, createComponentRef, createExtension, createExtensionBlueprint, createExtensionDataRef, createExtensionInput, createExternalRouteRef, createFrontendModule, createFrontendPlugin, createRouteRef, createSubRouteRef, iconsApiRef, routeResolutionApiRef, useAnalytics, useComponentRef, useRouteRef, useRouteRefParams };
1528
+ export { type AnalyticsApi, AnalyticsContext, type AnalyticsContextValue, type AnalyticsEvent, type AnalyticsEventAttributes, type AnalyticsTracker, type AnyExtensionDataRef, type AnyExternalRoutes, type AnyRouteRefParams, type AnyRoutes, ApiBlueprint, type AppNode, type AppNodeEdges, type AppNodeInstance, type AppNodeSpec, AppRootElementBlueprint, AppRootWrapperBlueprint, type AppTree, type AppTreeApi, type CommonAnalyticsContext, type ComponentRef, type ComponentsApi, type ConfigurableExtensionDataRef, type CoreErrorBoundaryFallbackProps, type CoreNotFoundErrorPageProps, type CoreProgressProps, type CreateExtensionBlueprintOptions, type CreateExtensionOptions, type CreateFrontendModuleOptions, type DialogApi, type DialogApiDialog, type Extension, type ExtensionAttachToSpec, type ExtensionBlueprint, type ExtensionBlueprintParameters, ExtensionBoundary, type ExtensionBoundaryProps, type ExtensionDataContainer, type ExtensionDataRef, type ExtensionDataRefToValue, type ExtensionDataValue, type ExtensionDefinition, type ExtensionDefinitionParameters, type ExtensionFactoryMiddleware, type ExtensionInput, type ExternalRouteRef, type FeatureFlagConfig, type FrontendModule, type FrontendPlugin, IconBundleBlueprint, type IconComponent, type IconsApi, NavItemBlueprint, NavLogoBlueprint, PageBlueprint, type PluginOptions, type PortableSchema, type ResolveInputValueOverrides, type ResolvedExtensionInput, type ResolvedExtensionInputs, type RouteFunc, type RouteRef, type RouteResolutionApi, type RouteResolutionApiResolveOptions, RouterBlueprint, SignInPageBlueprint, type SubRouteRef, ThemeBlueprint, TranslationBlueprint, analyticsApiRef, appTreeApiRef, componentsApiRef, coreComponentRefs, coreExtensionData, createComponentExtension, createComponentRef, createExtension, createExtensionBlueprint, createExtensionDataRef, createExtensionInput, createExternalRouteRef, createFrontendModule, createFrontendPlugin, createRouteRef, createSubRouteRef, dialogApiRef, iconsApiRef, routeResolutionApiRef, useAnalytics, useComponentRef, useRouteRef, useRouteRefParams };
package/dist/index.esm.js CHANGED
@@ -4,6 +4,7 @@ export { appTreeApiRef } from './apis/definitions/AppTreeApi.esm.js';
4
4
  export { SessionState, alertApiRef, appThemeApiRef, atlassianAuthApiRef, bitbucketAuthApiRef, bitbucketServerAuthApiRef, configApiRef, createApiFactory, createApiRef, discoveryApiRef, errorApiRef, featureFlagsApiRef, fetchApiRef, githubAuthApiRef, gitlabAuthApiRef, googleAuthApiRef, identityApiRef, microsoftAuthApiRef, oauthRequestApiRef, oktaAuthApiRef, oneloginAuthApiRef, storageApiRef, useApi, useApiHolder, vmwareCloudAuthApiRef, withApis } from '@backstage/core-plugin-api';
5
5
  export { componentsApiRef, useComponentRef } from './apis/definitions/ComponentsApi.esm.js';
6
6
  export { iconsApiRef } from './apis/definitions/IconsApi.esm.js';
7
+ export { dialogApiRef } from './apis/definitions/DialogApi.esm.js';
7
8
  export { routeResolutionApiRef } from './apis/definitions/RouteResolutionApi.esm.js';
8
9
  export { analyticsApiRef } from './apis/definitions/AnalyticsApi.esm.js';
9
10
  export { ApiBlueprint } from './blueprints/ApiBlueprint.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -4,6 +4,7 @@ import '../apis/definitions/AppTreeApi.esm.js';
4
4
  import { useApi } from '@backstage/core-plugin-api';
5
5
  import '../apis/definitions/ComponentsApi.esm.js';
6
6
  import '../apis/definitions/IconsApi.esm.js';
7
+ import '../apis/definitions/DialogApi.esm.js';
7
8
  import { routeResolutionApiRef } from '../apis/definitions/RouteResolutionApi.esm.js';
8
9
  import '../apis/definitions/AnalyticsApi.esm.js';
9
10
 
@@ -1 +1 @@
1
- {"version":3,"file":"useRouteRef.esm.js","sources":["../../src/routing/useRouteRef.tsx"],"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 { useMemo } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { AnyRouteRefParams } from './types';\nimport { RouteRef } from './RouteRef';\nimport { SubRouteRef } from './SubRouteRef';\nimport { ExternalRouteRef } from './ExternalRouteRef';\nimport { RouteFunc, routeResolutionApiRef, useApi } from '../apis';\n\n/**\n * React hook for constructing URLs to routes.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}\n *\n * @param routeRef - The ref to route that should be converted to URL.\n * @returns A function that will in turn return the concrete URL of the `routeRef`, or `undefined` if the route is not available.\n * @public\n */\nexport function useRouteRef<TParams extends AnyRouteRefParams>(\n routeRef:\n | RouteRef<TParams>\n | SubRouteRef<TParams>\n | ExternalRouteRef<TParams>,\n): RouteFunc<TParams> | undefined {\n const { pathname } = useLocation();\n const routeResolutionApi = useApi(routeResolutionApiRef);\n\n const routeFunc = useMemo(\n () => routeResolutionApi.resolve(routeRef, { sourcePath: pathname }),\n [routeResolutionApi, routeRef, pathname],\n );\n\n return routeFunc;\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCO,SAAS,YACd,QAIgC,EAAA;AAChC,EAAM,MAAA,EAAE,QAAS,EAAA,GAAI,WAAY,EAAA;AACjC,EAAM,MAAA,kBAAA,GAAqB,OAAO,qBAAqB,CAAA;AAEvD,EAAA,MAAM,SAAY,GAAA,OAAA;AAAA,IAChB,MAAM,kBAAmB,CAAA,OAAA,CAAQ,UAAU,EAAE,UAAA,EAAY,UAAU,CAAA;AAAA,IACnE,CAAC,kBAAoB,EAAA,QAAA,EAAU,QAAQ;AAAA,GACzC;AAEA,EAAO,OAAA,SAAA;AACT;;;;"}
1
+ {"version":3,"file":"useRouteRef.esm.js","sources":["../../src/routing/useRouteRef.tsx"],"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 { useMemo } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { AnyRouteRefParams } from './types';\nimport { RouteRef } from './RouteRef';\nimport { SubRouteRef } from './SubRouteRef';\nimport { ExternalRouteRef } from './ExternalRouteRef';\nimport { RouteFunc, routeResolutionApiRef, useApi } from '../apis';\n\n/**\n * React hook for constructing URLs to routes.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}\n *\n * @param routeRef - The ref to route that should be converted to URL.\n * @returns A function that will in turn return the concrete URL of the `routeRef`, or `undefined` if the route is not available.\n * @public\n */\nexport function useRouteRef<TParams extends AnyRouteRefParams>(\n routeRef:\n | RouteRef<TParams>\n | SubRouteRef<TParams>\n | ExternalRouteRef<TParams>,\n): RouteFunc<TParams> | undefined {\n const { pathname } = useLocation();\n const routeResolutionApi = useApi(routeResolutionApiRef);\n\n const routeFunc = useMemo(\n () => routeResolutionApi.resolve(routeRef, { sourcePath: pathname }),\n [routeResolutionApi, routeRef, pathname],\n );\n\n return routeFunc;\n}\n"],"names":[],"mappings":";;;;;;;;;;AAmCO,SAAS,YACd,QAIgC,EAAA;AAChC,EAAM,MAAA,EAAE,QAAS,EAAA,GAAI,WAAY,EAAA;AACjC,EAAM,MAAA,kBAAA,GAAqB,OAAO,qBAAqB,CAAA;AAEvD,EAAA,MAAM,SAAY,GAAA,OAAA;AAAA,IAChB,MAAM,kBAAmB,CAAA,OAAA,CAAQ,UAAU,EAAE,UAAA,EAAY,UAAU,CAAA;AAAA,IACnE,CAAC,kBAAoB,EAAA,QAAA,EAAU,QAAQ;AAAA,GACzC;AAEA,EAAO,OAAA,SAAA;AACT;;;;"}
@@ -1,7 +1,7 @@
1
1
  import { resolveInputOverrides } from './resolveInputOverrides.esm.js';
2
- import { createExtensionDataContainer } from './createExtensionDataContainer.esm.js';
3
2
  import { createSchemaFromZod } from '../schema/createSchemaFromZod.esm.js';
4
3
  import { OpaqueExtensionDefinition } from '../frontend-internal/src/wiring/InternalExtensionDefinition.esm.js';
4
+ import { createExtensionDataContainer } from '../frontend-internal/src/wiring/createExtensionDataContainer.esm.js';
5
5
  import '../frontend-internal/src/wiring/InternalFrontendPlugin.esm.js';
6
6
 
7
7
  const ctxParamsSymbol = Symbol("params");
@@ -1 +1 @@
1
- {"version":3,"file":"createExtension.esm.js","sources":["../../src/wiring/createExtension.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ApiHolder, AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport {\n ResolveInputValueOverrides,\n resolveInputOverrides,\n} from './resolveInputOverrides';\nimport {\n ExtensionDataContainer,\n createExtensionDataContainer,\n} from './createExtensionDataContainer';\nimport {\n AnyExtensionDataRef,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\nimport { z } from 'zod';\nimport { createSchemaFromZod } from '../schema/createSchemaFromZod';\nimport { OpaqueExtensionDefinition } from '@internal/frontend';\n\n/**\n * This symbol is used to pass parameter overrides from the extension override to the blueprint factory\n * @internal\n */\nexport const ctxParamsSymbol = Symbol('params');\n\n/**\n * Convert a single extension input into a matching resolved input.\n * @public\n */\nexport type ResolvedExtensionInput<\n TExtensionInput extends ExtensionInput<any, any>,\n> = TExtensionInput['extensionData'] extends Array<AnyExtensionDataRef>\n ? {\n node: AppNode;\n } & ExtensionDataContainer<TExtensionInput['extensionData'][number]>\n : never;\n\n/**\n * Converts an extension input map into a matching collection of resolved inputs.\n * @public\n */\nexport type ResolvedExtensionInputs<\n TInputs extends {\n [name in string]: ExtensionInput<any, any>;\n },\n> = {\n [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton']\n ? Array<Expand<ResolvedExtensionInput<TInputs[InputName]>>>\n : false extends TInputs[InputName]['config']['optional']\n ? Expand<ResolvedExtensionInput<TInputs[InputName]>>\n : Expand<ResolvedExtensionInput<TInputs[InputName]> | undefined>;\n};\n\ntype ToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I,\n) => void\n ? I\n : never;\n\ntype PopUnion<U> = ToIntersection<\n U extends any ? () => U : never\n> extends () => infer R\n ? [rest: Exclude<U, R>, next: R]\n : undefined;\n\n/** @ignore */\ntype JoinStringUnion<\n U,\n TDiv extends string = ', ',\n TResult extends string = '',\n> = PopUnion<U> extends [infer IRest extends string, infer INext extends string]\n ? TResult extends ''\n ? JoinStringUnion<IRest, TDiv, INext>\n : JoinStringUnion<IRest, TDiv, `${TResult}${TDiv}${INext}`>\n : TResult;\n\n/** @ignore */\nexport type VerifyExtensionFactoryOutput<\n UDeclaredOutput extends AnyExtensionDataRef,\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = (\n UDeclaredOutput extends any\n ? UDeclaredOutput['config']['optional'] extends true\n ? never\n : UDeclaredOutput['id']\n : never\n) extends infer IRequiredOutputIds\n ? [IRequiredOutputIds] extends [UFactoryOutput['id']]\n ? [UFactoryOutput['id']] extends [UDeclaredOutput['id']]\n ? {}\n : `Error: The extension factory has undeclared output(s): ${JoinStringUnion<\n Exclude<UFactoryOutput['id'], UDeclaredOutput['id']>\n >}`\n : `Error: The extension factory is missing the following output(s): ${JoinStringUnion<\n Exclude<IRequiredOutputIds, UFactoryOutput['id']>\n >}`\n : never;\n\n/** @public */\nexport type ExtensionAttachToSpec =\n | { id: string; input: string }\n | Array<{ id: string; input: string }>;\n\n/** @public */\nexport type CreateExtensionOptions<\n TKind extends string | undefined,\n TName extends string | undefined,\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = {\n kind?: TKind;\n name?: TName;\n attachTo: ExtensionAttachToSpec;\n disabled?: boolean;\n inputs?: TInputs;\n output: Array<UOutput>;\n config?: {\n schema: TConfigSchema;\n };\n factory(context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }): Iterable<UFactoryOutput>;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport type ExtensionDefinitionParameters = {\n kind?: string;\n name?: string;\n configInput?: { [K in string]: any };\n config?: { [K in string]: any };\n output?: AnyExtensionDataRef;\n inputs?: {\n [KName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n };\n params?: object;\n};\n\n/** @public */\nexport type ExtensionDefinition<\n T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters,\n> = {\n $$type: '@backstage/ExtensionDefinition';\n readonly T: T;\n\n override<\n TExtensionConfigSchema extends {\n [key in string]: (zImpl: typeof z) => z.ZodType;\n },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends AnyExtensionDataRef,\n TExtraInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n >(\n args: Expand<\n {\n attachTo?: ExtensionAttachToSpec;\n disabled?: boolean;\n inputs?: TExtraInputs & {\n [KName in keyof T['inputs']]?: `Error: Input '${KName &\n string}' is already defined in parent definition`;\n };\n output?: Array<UNewOutput>;\n config?: {\n schema: TExtensionConfigSchema & {\n [KName in keyof T['config']]?: `Error: Config key '${KName &\n string}' is already defined in parent schema`;\n };\n };\n factory?(\n originalFactory: (\n context?: Expand<\n {\n config?: T['config'];\n inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;\n } & ([T['params']] extends [never]\n ? {}\n : { params?: Partial<T['params']> })\n >,\n ) => ExtensionDataContainer<NonNullable<T['output']>>,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: T['config'] & {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n } & ([T['params']] extends [never]\n ? {}\n : { params?: Partial<T['params']> })\n > &\n VerifyExtensionFactoryOutput<\n AnyExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UFactoryOutput\n >,\n ): ExtensionDefinition<{\n kind: T['kind'];\n name: T['name'];\n output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;\n inputs: T['inputs'] & TExtraInputs;\n config: T['config'] & {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n };\n configInput: T['configInput'] &\n z.input<\n z.ZodObject<{\n [key in keyof TExtensionConfigSchema]: ReturnType<\n TExtensionConfigSchema[key]\n >;\n }>\n >;\n }>;\n};\n\n/** @public */\nexport function createExtension<\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n const TKind extends string | undefined = undefined,\n const TName extends string | undefined = undefined,\n>(\n options: CreateExtensionOptions<\n TKind,\n TName,\n UOutput,\n TInputs,\n TConfigSchema,\n UFactoryOutput\n >,\n): ExtensionDefinition<{\n config: string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n };\n configInput: string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >;\n output: UOutput;\n inputs: TInputs;\n params: never;\n kind: string | undefined extends TKind ? undefined : TKind;\n name: string | undefined extends TName ? undefined : TName;\n}> {\n const schemaDeclaration = options.config?.schema;\n const configSchema =\n schemaDeclaration &&\n createSchemaFromZod(innerZ =>\n innerZ.object(\n Object.fromEntries(\n Object.entries(schemaDeclaration).map(([k, v]) => [k, v(innerZ)]),\n ),\n ),\n );\n\n return OpaqueExtensionDefinition.createInstance('v2', {\n T: undefined as unknown as {\n config: string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<\n ReturnType<TConfigSchema[key]>\n >;\n };\n configInput: string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >;\n output: UOutput;\n inputs: TInputs;\n kind: string | undefined extends TKind ? undefined : TKind;\n name: string | undefined extends TName ? undefined : TName;\n },\n kind: options.kind,\n name: options.name,\n attachTo: options.attachTo,\n disabled: options.disabled ?? false,\n inputs: options.inputs ?? {},\n output: options.output,\n configSchema,\n factory: options.factory,\n toString() {\n const parts: string[] = [];\n if (options.kind) {\n parts.push(`kind=${options.kind}`);\n }\n if (options.name) {\n parts.push(`name=${options.name}`);\n }\n parts.push(\n `attachTo=${[options.attachTo]\n .flat()\n .map(a => `${a.id}@${a.input}`)\n .join('+')}`,\n );\n return `ExtensionDefinition{${parts.join(',')}}`;\n },\n override(overrideOptions) {\n if (!Array.isArray(options.output)) {\n throw new Error(\n 'Cannot override an extension that is not declared using the new format with outputs as an array',\n );\n }\n\n // TODO(Rugvip): Making this a type check would be optimal, but it seems\n // like it's tricky to add that and still have the type\n // inference work correctly for the factory output.\n if (overrideOptions.output && !overrideOptions.factory) {\n throw new Error(\n 'Refused to override output without also overriding factory',\n );\n }\n // TODO(Rugvip): Similar to above, would be nice to error during type checking, but don't want to complicate the types too much\n if (overrideOptions.params && overrideOptions.factory) {\n throw new Error(\n 'Refused to override params and factory at the same time',\n );\n }\n\n return createExtension({\n kind: options.kind,\n name: options.name,\n attachTo: overrideOptions.attachTo ?? options.attachTo,\n disabled: overrideOptions.disabled ?? options.disabled,\n inputs: { ...overrideOptions.inputs, ...options.inputs },\n output: (overrideOptions.output ??\n options.output) as AnyExtensionDataRef[],\n config:\n options.config || overrideOptions.config\n ? {\n schema: {\n ...options.config?.schema,\n ...overrideOptions.config?.schema,\n },\n }\n : undefined,\n factory: ({ node, apis, config, inputs }) => {\n if (!overrideOptions.factory) {\n return options.factory({\n node,\n apis,\n config: config as any,\n inputs: inputs as any,\n [ctxParamsSymbol as any]: overrideOptions.params,\n });\n }\n const parentResult = overrideOptions.factory(\n (innerContext): ExtensionDataContainer<UOutput> => {\n return createExtensionDataContainer<UOutput>(\n options.factory({\n node,\n apis,\n config: (innerContext?.config ?? config) as any,\n inputs: resolveInputOverrides(\n options.inputs,\n inputs,\n innerContext?.inputs,\n ) as any,\n [ctxParamsSymbol as any]: innerContext?.params,\n }) as Iterable<any>,\n options.output,\n );\n },\n {\n node,\n apis,\n config: config as any,\n inputs: inputs as any,\n },\n );\n\n const deduplicatedResult = new Map<\n string,\n ExtensionDataValue<any, any>\n >();\n for (const item of parentResult) {\n deduplicatedResult.set(item.id, item);\n }\n\n return deduplicatedResult.values();\n },\n }) as ExtensionDefinition<any>;\n },\n });\n}\n"],"names":[],"mappings":";;;;;;AAuCa,MAAA,eAAA,GAAkB,OAAO,QAAQ;AA0NvC,SAAS,gBAad,OA0BC,EAAA;AACD,EAAM,MAAA,iBAAA,GAAoB,QAAQ,MAAQ,EAAA,MAAA;AAC1C,EAAA,MAAM,eACJ,iBACA,IAAA,mBAAA;AAAA,IAAoB,YAClB,MAAO,CAAA,MAAA;AAAA,MACL,MAAO,CAAA,WAAA;AAAA,QACL,MAAO,CAAA,OAAA,CAAQ,iBAAiB,CAAA,CAAE,IAAI,CAAC,CAAC,CAAG,EAAA,CAAC,MAAM,CAAC,CAAA,EAAG,CAAE,CAAA,MAAM,CAAC,CAAC;AAAA;AAClE;AACF,GACF;AAEF,EAAO,OAAA,yBAAA,CAA0B,eAAe,IAAM,EAAA;AAAA,IACpD,CAAG,EAAA,KAAA,CAAA;AAAA,IAoBH,MAAM,OAAQ,CAAA,IAAA;AAAA,IACd,MAAM,OAAQ,CAAA,IAAA;AAAA,IACd,UAAU,OAAQ,CAAA,QAAA;AAAA,IAClB,QAAA,EAAU,QAAQ,QAAY,IAAA,KAAA;AAAA,IAC9B,MAAA,EAAQ,OAAQ,CAAA,MAAA,IAAU,EAAC;AAAA,IAC3B,QAAQ,OAAQ,CAAA,MAAA;AAAA,IAChB,YAAA;AAAA,IACA,SAAS,OAAQ,CAAA,OAAA;AAAA,IACjB,QAAW,GAAA;AACT,MAAA,MAAM,QAAkB,EAAC;AACzB,MAAA,IAAI,QAAQ,IAAM,EAAA;AAChB,QAAA,KAAA,CAAM,IAAK,CAAA,CAAA,KAAA,EAAQ,OAAQ,CAAA,IAAI,CAAE,CAAA,CAAA;AAAA;AAEnC,MAAA,IAAI,QAAQ,IAAM,EAAA;AAChB,QAAA,KAAA,CAAM,IAAK,CAAA,CAAA,KAAA,EAAQ,OAAQ,CAAA,IAAI,CAAE,CAAA,CAAA;AAAA;AAEnC,MAAM,KAAA,CAAA,IAAA;AAAA,QACJ,YAAY,CAAC,OAAA,CAAQ,QAAQ,CAC1B,CAAA,IAAA,GACA,GAAI,CAAA,CAAA,CAAA,KAAK,GAAG,CAAE,CAAA,EAAE,IAAI,CAAE,CAAA,KAAK,EAAE,CAC7B,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,OACd;AACA,MAAA,OAAO,CAAuB,oBAAA,EAAA,KAAA,CAAM,IAAK,CAAA,GAAG,CAAC,CAAA,CAAA,CAAA;AAAA,KAC/C;AAAA,IACA,SAAS,eAAiB,EAAA;AACxB,MAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,OAAA,CAAQ,MAAM,CAAG,EAAA;AAClC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA;AAMF,MAAA,IAAI,eAAgB,CAAA,MAAA,IAAU,CAAC,eAAA,CAAgB,OAAS,EAAA;AACtD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA;AAGF,MAAI,IAAA,eAAA,CAAgB,MAAU,IAAA,eAAA,CAAgB,OAAS,EAAA;AACrD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA;AAGF,MAAA,OAAO,eAAgB,CAAA;AAAA,QACrB,MAAM,OAAQ,CAAA,IAAA;AAAA,QACd,MAAM,OAAQ,CAAA,IAAA;AAAA,QACd,QAAA,EAAU,eAAgB,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QAC9C,QAAA,EAAU,eAAgB,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QAC9C,QAAQ,EAAE,GAAG,gBAAgB,MAAQ,EAAA,GAAG,QAAQ,MAAO,EAAA;AAAA,QACvD,MAAA,EAAS,eAAgB,CAAA,MAAA,IACvB,OAAQ,CAAA,MAAA;AAAA,QACV,MACE,EAAA,OAAA,CAAQ,MAAU,IAAA,eAAA,CAAgB,MAC9B,GAAA;AAAA,UACE,MAAQ,EAAA;AAAA,YACN,GAAG,QAAQ,MAAQ,EAAA,MAAA;AAAA,YACnB,GAAG,gBAAgB,MAAQ,EAAA;AAAA;AAC7B,SAEF,GAAA,KAAA,CAAA;AAAA,QACN,SAAS,CAAC,EAAE,MAAM,IAAM,EAAA,MAAA,EAAQ,QAAa,KAAA;AAC3C,UAAI,IAAA,CAAC,gBAAgB,OAAS,EAAA;AAC5B,YAAA,OAAO,QAAQ,OAAQ,CAAA;AAAA,cACrB,IAAA;AAAA,cACA,IAAA;AAAA,cACA,MAAA;AAAA,cACA,MAAA;AAAA,cACA,CAAC,eAAsB,GAAG,eAAgB,CAAA;AAAA,aAC3C,CAAA;AAAA;AAEH,UAAA,MAAM,eAAe,eAAgB,CAAA,OAAA;AAAA,YACnC,CAAC,YAAkD,KAAA;AACjD,cAAO,OAAA,4BAAA;AAAA,gBACL,QAAQ,OAAQ,CAAA;AAAA,kBACd,IAAA;AAAA,kBACA,IAAA;AAAA,kBACA,MAAA,EAAS,cAAc,MAAU,IAAA,MAAA;AAAA,kBACjC,MAAQ,EAAA,qBAAA;AAAA,oBACN,OAAQ,CAAA,MAAA;AAAA,oBACR,MAAA;AAAA,oBACA,YAAc,EAAA;AAAA,mBAChB;AAAA,kBACA,CAAC,eAAsB,GAAG,YAAc,EAAA;AAAA,iBACzC,CAAA;AAAA,gBACD,OAAQ,CAAA;AAAA,eACV;AAAA,aACF;AAAA,YACA;AAAA,cACE,IAAA;AAAA,cACA,IAAA;AAAA,cACA,MAAA;AAAA,cACA;AAAA;AACF,WACF;AAEA,UAAM,MAAA,kBAAA,uBAAyB,GAG7B,EAAA;AACF,UAAA,KAAA,MAAW,QAAQ,YAAc,EAAA;AAC/B,YAAmB,kBAAA,CAAA,GAAA,CAAI,IAAK,CAAA,EAAA,EAAI,IAAI,CAAA;AAAA;AAGtC,UAAA,OAAO,mBAAmB,MAAO,EAAA;AAAA;AACnC,OACD,CAAA;AAAA;AACH,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"createExtension.esm.js","sources":["../../src/wiring/createExtension.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ApiHolder, AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport {\n ResolveInputValueOverrides,\n resolveInputOverrides,\n} from './resolveInputOverrides';\nimport { createExtensionDataContainer } from '@internal/frontend';\nimport {\n AnyExtensionDataRef,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\nimport { z } from 'zod';\nimport { createSchemaFromZod } from '../schema/createSchemaFromZod';\nimport { OpaqueExtensionDefinition } from '@internal/frontend';\nimport { ExtensionDataContainer } from './types';\n\n/**\n * This symbol is used to pass parameter overrides from the extension override to the blueprint factory\n * @internal\n */\nexport const ctxParamsSymbol = Symbol('params');\n\n/**\n * Convert a single extension input into a matching resolved input.\n * @public\n */\nexport type ResolvedExtensionInput<\n TExtensionInput extends ExtensionInput<any, any>,\n> = TExtensionInput['extensionData'] extends Array<AnyExtensionDataRef>\n ? {\n node: AppNode;\n } & ExtensionDataContainer<TExtensionInput['extensionData'][number]>\n : never;\n\n/**\n * Converts an extension input map into a matching collection of resolved inputs.\n * @public\n */\nexport type ResolvedExtensionInputs<\n TInputs extends {\n [name in string]: ExtensionInput<any, any>;\n },\n> = {\n [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton']\n ? Array<Expand<ResolvedExtensionInput<TInputs[InputName]>>>\n : false extends TInputs[InputName]['config']['optional']\n ? Expand<ResolvedExtensionInput<TInputs[InputName]>>\n : Expand<ResolvedExtensionInput<TInputs[InputName]> | undefined>;\n};\n\ntype ToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I,\n) => void\n ? I\n : never;\n\ntype PopUnion<U> = ToIntersection<\n U extends any ? () => U : never\n> extends () => infer R\n ? [rest: Exclude<U, R>, next: R]\n : undefined;\n\n/** @ignore */\ntype JoinStringUnion<\n U,\n TDiv extends string = ', ',\n TResult extends string = '',\n> = PopUnion<U> extends [infer IRest extends string, infer INext extends string]\n ? TResult extends ''\n ? JoinStringUnion<IRest, TDiv, INext>\n : JoinStringUnion<IRest, TDiv, `${TResult}${TDiv}${INext}`>\n : TResult;\n\n/** @ignore */\nexport type VerifyExtensionFactoryOutput<\n UDeclaredOutput extends AnyExtensionDataRef,\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = (\n UDeclaredOutput extends any\n ? UDeclaredOutput['config']['optional'] extends true\n ? never\n : UDeclaredOutput['id']\n : never\n) extends infer IRequiredOutputIds\n ? [IRequiredOutputIds] extends [UFactoryOutput['id']]\n ? [UFactoryOutput['id']] extends [UDeclaredOutput['id']]\n ? {}\n : `Error: The extension factory has undeclared output(s): ${JoinStringUnion<\n Exclude<UFactoryOutput['id'], UDeclaredOutput['id']>\n >}`\n : `Error: The extension factory is missing the following output(s): ${JoinStringUnion<\n Exclude<IRequiredOutputIds, UFactoryOutput['id']>\n >}`\n : never;\n\n/** @public */\nexport type ExtensionAttachToSpec =\n | { id: string; input: string }\n | Array<{ id: string; input: string }>;\n\n/** @public */\nexport type CreateExtensionOptions<\n TKind extends string | undefined,\n TName extends string | undefined,\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = {\n kind?: TKind;\n name?: TName;\n attachTo: ExtensionAttachToSpec;\n disabled?: boolean;\n inputs?: TInputs;\n output: Array<UOutput>;\n config?: {\n schema: TConfigSchema;\n };\n factory(context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }): Iterable<UFactoryOutput>;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport type ExtensionDefinitionParameters = {\n kind?: string;\n name?: string;\n configInput?: { [K in string]: any };\n config?: { [K in string]: any };\n output?: AnyExtensionDataRef;\n inputs?: {\n [KName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n };\n params?: object;\n};\n\n/** @public */\nexport type ExtensionDefinition<\n T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters,\n> = {\n $$type: '@backstage/ExtensionDefinition';\n readonly T: T;\n\n override<\n TExtensionConfigSchema extends {\n [key in string]: (zImpl: typeof z) => z.ZodType;\n },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends AnyExtensionDataRef,\n TExtraInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n >(\n args: Expand<\n {\n attachTo?: ExtensionAttachToSpec;\n disabled?: boolean;\n inputs?: TExtraInputs & {\n [KName in keyof T['inputs']]?: `Error: Input '${KName &\n string}' is already defined in parent definition`;\n };\n output?: Array<UNewOutput>;\n config?: {\n schema: TExtensionConfigSchema & {\n [KName in keyof T['config']]?: `Error: Config key '${KName &\n string}' is already defined in parent schema`;\n };\n };\n factory?(\n originalFactory: (\n context?: Expand<\n {\n config?: T['config'];\n inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;\n } & ([T['params']] extends [never]\n ? {}\n : { params?: Partial<T['params']> })\n >,\n ) => ExtensionDataContainer<NonNullable<T['output']>>,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: T['config'] & {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n } & ([T['params']] extends [never]\n ? {}\n : { params?: Partial<T['params']> })\n > &\n VerifyExtensionFactoryOutput<\n AnyExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UFactoryOutput\n >,\n ): ExtensionDefinition<{\n kind: T['kind'];\n name: T['name'];\n output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;\n inputs: T['inputs'] & TExtraInputs;\n config: T['config'] & {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n };\n configInput: T['configInput'] &\n z.input<\n z.ZodObject<{\n [key in keyof TExtensionConfigSchema]: ReturnType<\n TExtensionConfigSchema[key]\n >;\n }>\n >;\n }>;\n};\n\n/** @public */\nexport function createExtension<\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n const TKind extends string | undefined = undefined,\n const TName extends string | undefined = undefined,\n>(\n options: CreateExtensionOptions<\n TKind,\n TName,\n UOutput,\n TInputs,\n TConfigSchema,\n UFactoryOutput\n >,\n): ExtensionDefinition<{\n config: string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n };\n configInput: string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >;\n output: UOutput;\n inputs: TInputs;\n params: never;\n kind: string | undefined extends TKind ? undefined : TKind;\n name: string | undefined extends TName ? undefined : TName;\n}> {\n const schemaDeclaration = options.config?.schema;\n const configSchema =\n schemaDeclaration &&\n createSchemaFromZod(innerZ =>\n innerZ.object(\n Object.fromEntries(\n Object.entries(schemaDeclaration).map(([k, v]) => [k, v(innerZ)]),\n ),\n ),\n );\n\n return OpaqueExtensionDefinition.createInstance('v2', {\n T: undefined as unknown as {\n config: string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<\n ReturnType<TConfigSchema[key]>\n >;\n };\n configInput: string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >;\n output: UOutput;\n inputs: TInputs;\n kind: string | undefined extends TKind ? undefined : TKind;\n name: string | undefined extends TName ? undefined : TName;\n },\n kind: options.kind,\n name: options.name,\n attachTo: options.attachTo,\n disabled: options.disabled ?? false,\n inputs: options.inputs ?? {},\n output: options.output,\n configSchema,\n factory: options.factory,\n toString() {\n const parts: string[] = [];\n if (options.kind) {\n parts.push(`kind=${options.kind}`);\n }\n if (options.name) {\n parts.push(`name=${options.name}`);\n }\n parts.push(\n `attachTo=${[options.attachTo]\n .flat()\n .map(a => `${a.id}@${a.input}`)\n .join('+')}`,\n );\n return `ExtensionDefinition{${parts.join(',')}}`;\n },\n override(overrideOptions) {\n if (!Array.isArray(options.output)) {\n throw new Error(\n 'Cannot override an extension that is not declared using the new format with outputs as an array',\n );\n }\n\n // TODO(Rugvip): Making this a type check would be optimal, but it seems\n // like it's tricky to add that and still have the type\n // inference work correctly for the factory output.\n if (overrideOptions.output && !overrideOptions.factory) {\n throw new Error(\n 'Refused to override output without also overriding factory',\n );\n }\n // TODO(Rugvip): Similar to above, would be nice to error during type checking, but don't want to complicate the types too much\n if (overrideOptions.params && overrideOptions.factory) {\n throw new Error(\n 'Refused to override params and factory at the same time',\n );\n }\n\n return createExtension({\n kind: options.kind,\n name: options.name,\n attachTo: overrideOptions.attachTo ?? options.attachTo,\n disabled: overrideOptions.disabled ?? options.disabled,\n inputs: { ...overrideOptions.inputs, ...options.inputs },\n output: (overrideOptions.output ??\n options.output) as AnyExtensionDataRef[],\n config:\n options.config || overrideOptions.config\n ? {\n schema: {\n ...options.config?.schema,\n ...overrideOptions.config?.schema,\n },\n }\n : undefined,\n factory: ({ node, apis, config, inputs }) => {\n if (!overrideOptions.factory) {\n return options.factory({\n node,\n apis,\n config: config as any,\n inputs: inputs as any,\n [ctxParamsSymbol as any]: overrideOptions.params,\n });\n }\n const parentResult = overrideOptions.factory(\n (innerContext): ExtensionDataContainer<UOutput> => {\n return createExtensionDataContainer<UOutput>(\n options.factory({\n node,\n apis,\n config: (innerContext?.config ?? config) as any,\n inputs: resolveInputOverrides(\n options.inputs,\n inputs,\n innerContext?.inputs,\n ) as any,\n [ctxParamsSymbol as any]: innerContext?.params,\n }) as Iterable<any>,\n options.output,\n );\n },\n {\n node,\n apis,\n config: config as any,\n inputs: inputs as any,\n },\n );\n\n const deduplicatedResult = new Map<\n string,\n ExtensionDataValue<any, any>\n >();\n for (const item of parentResult) {\n deduplicatedResult.set(item.id, item);\n }\n\n return deduplicatedResult.values();\n },\n }) as ExtensionDefinition<any>;\n },\n });\n}\n"],"names":[],"mappings":";;;;;;AAqCa,MAAA,eAAA,GAAkB,OAAO,QAAQ;AA0NvC,SAAS,gBAad,OA0BC,EAAA;AACD,EAAM,MAAA,iBAAA,GAAoB,QAAQ,MAAQ,EAAA,MAAA;AAC1C,EAAA,MAAM,eACJ,iBACA,IAAA,mBAAA;AAAA,IAAoB,YAClB,MAAO,CAAA,MAAA;AAAA,MACL,MAAO,CAAA,WAAA;AAAA,QACL,MAAO,CAAA,OAAA,CAAQ,iBAAiB,CAAA,CAAE,IAAI,CAAC,CAAC,CAAG,EAAA,CAAC,MAAM,CAAC,CAAA,EAAG,CAAE,CAAA,MAAM,CAAC,CAAC;AAAA;AAClE;AACF,GACF;AAEF,EAAO,OAAA,yBAAA,CAA0B,eAAe,IAAM,EAAA;AAAA,IACpD,CAAG,EAAA,KAAA,CAAA;AAAA,IAoBH,MAAM,OAAQ,CAAA,IAAA;AAAA,IACd,MAAM,OAAQ,CAAA,IAAA;AAAA,IACd,UAAU,OAAQ,CAAA,QAAA;AAAA,IAClB,QAAA,EAAU,QAAQ,QAAY,IAAA,KAAA;AAAA,IAC9B,MAAA,EAAQ,OAAQ,CAAA,MAAA,IAAU,EAAC;AAAA,IAC3B,QAAQ,OAAQ,CAAA,MAAA;AAAA,IAChB,YAAA;AAAA,IACA,SAAS,OAAQ,CAAA,OAAA;AAAA,IACjB,QAAW,GAAA;AACT,MAAA,MAAM,QAAkB,EAAC;AACzB,MAAA,IAAI,QAAQ,IAAM,EAAA;AAChB,QAAA,KAAA,CAAM,IAAK,CAAA,CAAA,KAAA,EAAQ,OAAQ,CAAA,IAAI,CAAE,CAAA,CAAA;AAAA;AAEnC,MAAA,IAAI,QAAQ,IAAM,EAAA;AAChB,QAAA,KAAA,CAAM,IAAK,CAAA,CAAA,KAAA,EAAQ,OAAQ,CAAA,IAAI,CAAE,CAAA,CAAA;AAAA;AAEnC,MAAM,KAAA,CAAA,IAAA;AAAA,QACJ,YAAY,CAAC,OAAA,CAAQ,QAAQ,CAC1B,CAAA,IAAA,GACA,GAAI,CAAA,CAAA,CAAA,KAAK,GAAG,CAAE,CAAA,EAAE,IAAI,CAAE,CAAA,KAAK,EAAE,CAC7B,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,OACd;AACA,MAAA,OAAO,CAAuB,oBAAA,EAAA,KAAA,CAAM,IAAK,CAAA,GAAG,CAAC,CAAA,CAAA,CAAA;AAAA,KAC/C;AAAA,IACA,SAAS,eAAiB,EAAA;AACxB,MAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,OAAA,CAAQ,MAAM,CAAG,EAAA;AAClC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA;AAMF,MAAA,IAAI,eAAgB,CAAA,MAAA,IAAU,CAAC,eAAA,CAAgB,OAAS,EAAA;AACtD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA;AAGF,MAAI,IAAA,eAAA,CAAgB,MAAU,IAAA,eAAA,CAAgB,OAAS,EAAA;AACrD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA;AAGF,MAAA,OAAO,eAAgB,CAAA;AAAA,QACrB,MAAM,OAAQ,CAAA,IAAA;AAAA,QACd,MAAM,OAAQ,CAAA,IAAA;AAAA,QACd,QAAA,EAAU,eAAgB,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QAC9C,QAAA,EAAU,eAAgB,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QAC9C,QAAQ,EAAE,GAAG,gBAAgB,MAAQ,EAAA,GAAG,QAAQ,MAAO,EAAA;AAAA,QACvD,MAAA,EAAS,eAAgB,CAAA,MAAA,IACvB,OAAQ,CAAA,MAAA;AAAA,QACV,MACE,EAAA,OAAA,CAAQ,MAAU,IAAA,eAAA,CAAgB,MAC9B,GAAA;AAAA,UACE,MAAQ,EAAA;AAAA,YACN,GAAG,QAAQ,MAAQ,EAAA,MAAA;AAAA,YACnB,GAAG,gBAAgB,MAAQ,EAAA;AAAA;AAC7B,SAEF,GAAA,KAAA,CAAA;AAAA,QACN,SAAS,CAAC,EAAE,MAAM,IAAM,EAAA,MAAA,EAAQ,QAAa,KAAA;AAC3C,UAAI,IAAA,CAAC,gBAAgB,OAAS,EAAA;AAC5B,YAAA,OAAO,QAAQ,OAAQ,CAAA;AAAA,cACrB,IAAA;AAAA,cACA,IAAA;AAAA,cACA,MAAA;AAAA,cACA,MAAA;AAAA,cACA,CAAC,eAAsB,GAAG,eAAgB,CAAA;AAAA,aAC3C,CAAA;AAAA;AAEH,UAAA,MAAM,eAAe,eAAgB,CAAA,OAAA;AAAA,YACnC,CAAC,YAAkD,KAAA;AACjD,cAAO,OAAA,4BAAA;AAAA,gBACL,QAAQ,OAAQ,CAAA;AAAA,kBACd,IAAA;AAAA,kBACA,IAAA;AAAA,kBACA,MAAA,EAAS,cAAc,MAAU,IAAA,MAAA;AAAA,kBACjC,MAAQ,EAAA,qBAAA;AAAA,oBACN,OAAQ,CAAA,MAAA;AAAA,oBACR,MAAA;AAAA,oBACA,YAAc,EAAA;AAAA,mBAChB;AAAA,kBACA,CAAC,eAAsB,GAAG,YAAc,EAAA;AAAA,iBACzC,CAAA;AAAA,gBACD,OAAQ,CAAA;AAAA,eACV;AAAA,aACF;AAAA,YACA;AAAA,cACE,IAAA;AAAA,cACA,IAAA;AAAA,cACA,MAAA;AAAA,cACA;AAAA;AACF,WACF;AAEA,UAAM,MAAA,kBAAA,uBAAyB,GAG7B,EAAA;AACF,UAAA,KAAA,MAAW,QAAQ,YAAc,EAAA;AAC/B,YAAmB,kBAAA,CAAA,GAAA,CAAI,IAAK,CAAA,EAAA,EAAI,IAAI,CAAA;AAAA;AAGtC,UAAA,OAAO,mBAAmB,MAAO,EAAA;AAAA;AACnC,OACD,CAAA;AAAA;AACH,GACD,CAAA;AACH;;;;"}
@@ -1,6 +1,6 @@
1
1
  import { createExtension, ctxParamsSymbol } from './createExtension.esm.js';
2
- import { createExtensionDataContainer } from './createExtensionDataContainer.esm.js';
3
2
  import { resolveInputOverrides } from './resolveInputOverrides.esm.js';
3
+ import { createExtensionDataContainer } from '../frontend-internal/src/wiring/createExtensionDataContainer.esm.js';
4
4
 
5
5
  function createExtensionBlueprint(options) {
6
6
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"createExtensionBlueprint.esm.js","sources":["../../src/wiring/createExtensionBlueprint.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ApiHolder, AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport {\n ExtensionAttachToSpec,\n ExtensionDefinition,\n ResolvedExtensionInputs,\n VerifyExtensionFactoryOutput,\n createExtension,\n ctxParamsSymbol,\n} from './createExtension';\nimport { z } from 'zod';\nimport { ExtensionInput } from './createExtensionInput';\nimport {\n AnyExtensionDataRef,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport {\n ExtensionDataContainer,\n createExtensionDataContainer,\n} from './createExtensionDataContainer';\nimport {\n ResolveInputValueOverrides,\n resolveInputOverrides,\n} from './resolveInputOverrides';\n\n/**\n * @public\n */\nexport type CreateExtensionBlueprintOptions<\n TKind extends string,\n TName extends string | undefined,\n TParams,\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n TDataRefs extends { [name in string]: AnyExtensionDataRef },\n> = {\n kind: TKind;\n attachTo: ExtensionAttachToSpec;\n disabled?: boolean;\n inputs?: TInputs;\n output: Array<UOutput>;\n name?: TName;\n config?: {\n schema: TConfigSchema;\n };\n factory(\n params: TParams,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n\n dataRefs?: TDataRefs;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport type ExtensionBlueprintParameters = {\n kind: string;\n name?: string;\n params?: object;\n configInput?: { [K in string]: any };\n config?: { [K in string]: any };\n output?: AnyExtensionDataRef;\n inputs?: {\n [KName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n };\n dataRefs?: { [name in string]: AnyExtensionDataRef };\n};\n\n/**\n * @public\n */\nexport interface ExtensionBlueprint<\n T extends ExtensionBlueprintParameters = ExtensionBlueprintParameters,\n> {\n dataRefs: T['dataRefs'];\n\n make<TNewName extends string | undefined>(args: {\n name?: TNewName;\n attachTo?: ExtensionAttachToSpec;\n disabled?: boolean;\n params: T['params'];\n }): ExtensionDefinition<{\n kind: T['kind'];\n name: string | undefined extends TNewName ? T['name'] : TNewName;\n config: T['config'];\n configInput: T['configInput'];\n output: T['output'];\n inputs: T['inputs'];\n params: T['params'];\n }>;\n\n /**\n * Creates a new extension from the blueprint.\n *\n * You must either pass `params` directly, or define a `factory` that can\n * optionally call the original factory with the same params.\n */\n makeWithOverrides<\n TNewName extends string | undefined,\n TExtensionConfigSchema extends {\n [key in string]: (zImpl: typeof z) => z.ZodType;\n },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends AnyExtensionDataRef,\n TExtraInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n >(args: {\n name?: TNewName;\n attachTo?: ExtensionAttachToSpec;\n disabled?: boolean;\n inputs?: TExtraInputs & {\n [KName in keyof T['inputs']]?: `Error: Input '${KName &\n string}' is already defined in parent definition`;\n };\n output?: Array<UNewOutput>;\n config?: {\n schema: TExtensionConfigSchema & {\n [KName in keyof T['config']]?: `Error: Config key '${KName &\n string}' is already defined in parent schema`;\n };\n };\n factory(\n originalFactory: (\n params: T['params'],\n context?: {\n config?: T['config'];\n inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;\n },\n ) => ExtensionDataContainer<NonNullable<T['output']>>,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: T['config'] & {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;\n },\n ): Iterable<UFactoryOutput> &\n VerifyExtensionFactoryOutput<\n AnyExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UFactoryOutput\n >;\n }): ExtensionDefinition<{\n config: (string extends keyof TExtensionConfigSchema\n ? {}\n : {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n }) &\n T['config'];\n configInput: (string extends keyof TExtensionConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TExtensionConfigSchema]: ReturnType<\n TExtensionConfigSchema[key]\n >;\n }>\n >) &\n T['configInput'];\n output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;\n inputs: T['inputs'] & TExtraInputs;\n kind: T['kind'];\n name: string | undefined extends TNewName ? T['name'] : TNewName;\n params: T['params'];\n }>;\n}\n\n/**\n * A simpler replacement for wrapping up `createExtension` inside a kind or type. This allows for a cleaner API for creating\n * types and instances of those types.\n *\n * @public\n */\nexport function createExtensionBlueprint<\n TParams extends object,\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n TKind extends string,\n TName extends string | undefined = undefined,\n TDataRefs extends { [name in string]: AnyExtensionDataRef } = never,\n>(\n options: CreateExtensionBlueprintOptions<\n TKind,\n TName,\n TParams,\n UOutput,\n TInputs,\n TConfigSchema,\n UFactoryOutput,\n TDataRefs\n >,\n): ExtensionBlueprint<{\n kind: TKind;\n name: TName;\n params: TParams;\n output: UOutput;\n inputs: string extends keyof TInputs ? {} : TInputs;\n config: string extends keyof TConfigSchema\n ? {}\n : { [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>> };\n configInput: string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >;\n dataRefs: TDataRefs;\n}> {\n return {\n dataRefs: options.dataRefs,\n make(args) {\n return createExtension({\n kind: options.kind,\n name: args.name ?? options.name,\n attachTo: args.attachTo ?? options.attachTo,\n disabled: args.disabled ?? options.disabled,\n inputs: options.inputs,\n output: options.output as AnyExtensionDataRef[],\n config: options.config,\n factory: ctx =>\n options.factory(\n { ...args.params, ...(ctx as any)[ctxParamsSymbol] },\n ctx,\n ) as Iterable<ExtensionDataValue<any, any>>,\n }) as ExtensionDefinition;\n },\n makeWithOverrides(args) {\n return createExtension({\n kind: options.kind,\n name: args.name ?? options.name,\n attachTo: args.attachTo ?? options.attachTo,\n disabled: args.disabled ?? options.disabled,\n inputs: { ...args.inputs, ...options.inputs },\n output: (args.output ?? options.output) as AnyExtensionDataRef[],\n config:\n options.config || args.config\n ? {\n schema: {\n ...options.config?.schema,\n ...args.config?.schema,\n },\n }\n : undefined,\n factory: ctx => {\n const { node, config, inputs, apis } = ctx;\n return args.factory(\n (innerParams, innerContext) => {\n return createExtensionDataContainer<UOutput>(\n options.factory(\n { ...innerParams, ...(ctx as any)[ctxParamsSymbol] },\n {\n apis,\n node,\n config: (innerContext?.config ?? config) as any,\n inputs: resolveInputOverrides(\n options.inputs,\n inputs,\n innerContext?.inputs,\n ) as any,\n },\n ) as Iterable<any>,\n options.output,\n );\n },\n {\n apis,\n node,\n config: config as any,\n inputs: inputs as any,\n },\n ) as Iterable<ExtensionDataValue<any, any>>;\n },\n }) as ExtensionDefinition;\n },\n } as ExtensionBlueprint<{\n kind: TKind;\n name: TName;\n params: TParams;\n output: UOutput;\n inputs: string extends keyof TInputs ? {} : TInputs;\n config: string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n };\n configInput: string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >;\n dataRefs: TDataRefs;\n }>;\n}\n"],"names":[],"mappings":";;;;AAuNO,SAAS,yBAed,OA2BC,EAAA;AACD,EAAO,OAAA;AAAA,IACL,UAAU,OAAQ,CAAA,QAAA;AAAA,IAClB,KAAK,IAAM,EAAA;AACT,MAAA,OAAO,eAAgB,CAAA;AAAA,QACrB,MAAM,OAAQ,CAAA,IAAA;AAAA,QACd,IAAA,EAAM,IAAK,CAAA,IAAA,IAAQ,OAAQ,CAAA,IAAA;AAAA,QAC3B,QAAA,EAAU,IAAK,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QACnC,QAAA,EAAU,IAAK,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QACnC,QAAQ,OAAQ,CAAA,MAAA;AAAA,QAChB,QAAQ,OAAQ,CAAA,MAAA;AAAA,QAChB,QAAQ,OAAQ,CAAA,MAAA;AAAA,QAChB,OAAA,EAAS,SACP,OAAQ,CAAA,OAAA;AAAA,UACN,EAAE,GAAG,IAAA,CAAK,QAAQ,GAAI,GAAA,CAAY,eAAe,CAAE,EAAA;AAAA,UACnD;AAAA;AACF,OACH,CAAA;AAAA,KACH;AAAA,IACA,kBAAkB,IAAM,EAAA;AACtB,MAAA,OAAO,eAAgB,CAAA;AAAA,QACrB,MAAM,OAAQ,CAAA,IAAA;AAAA,QACd,IAAA,EAAM,IAAK,CAAA,IAAA,IAAQ,OAAQ,CAAA,IAAA;AAAA,QAC3B,QAAA,EAAU,IAAK,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QACnC,QAAA,EAAU,IAAK,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QACnC,QAAQ,EAAE,GAAG,KAAK,MAAQ,EAAA,GAAG,QAAQ,MAAO,EAAA;AAAA,QAC5C,MAAA,EAAS,IAAK,CAAA,MAAA,IAAU,OAAQ,CAAA,MAAA;AAAA,QAChC,MACE,EAAA,OAAA,CAAQ,MAAU,IAAA,IAAA,CAAK,MACnB,GAAA;AAAA,UACE,MAAQ,EAAA;AAAA,YACN,GAAG,QAAQ,MAAQ,EAAA,MAAA;AAAA,YACnB,GAAG,KAAK,MAAQ,EAAA;AAAA;AAClB,SAEF,GAAA,KAAA,CAAA;AAAA,QACN,SAAS,CAAO,GAAA,KAAA;AACd,UAAA,MAAM,EAAE,IAAA,EAAM,MAAQ,EAAA,MAAA,EAAQ,MAAS,GAAA,GAAA;AACvC,UAAA,OAAO,IAAK,CAAA,OAAA;AAAA,YACV,CAAC,aAAa,YAAiB,KAAA;AAC7B,cAAO,OAAA,4BAAA;AAAA,gBACL,OAAQ,CAAA,OAAA;AAAA,kBACN,EAAE,GAAG,WAAA,EAAa,GAAI,GAAA,CAAY,eAAe,CAAE,EAAA;AAAA,kBACnD;AAAA,oBACE,IAAA;AAAA,oBACA,IAAA;AAAA,oBACA,MAAA,EAAS,cAAc,MAAU,IAAA,MAAA;AAAA,oBACjC,MAAQ,EAAA,qBAAA;AAAA,sBACN,OAAQ,CAAA,MAAA;AAAA,sBACR,MAAA;AAAA,sBACA,YAAc,EAAA;AAAA;AAChB;AACF,iBACF;AAAA,gBACA,OAAQ,CAAA;AAAA,eACV;AAAA,aACF;AAAA,YACA;AAAA,cACE,IAAA;AAAA,cACA,IAAA;AAAA,cACA,MAAA;AAAA,cACA;AAAA;AACF,WACF;AAAA;AACF,OACD,CAAA;AAAA;AACH,GACF;AAoBF;;;;"}
1
+ {"version":3,"file":"createExtensionBlueprint.esm.js","sources":["../../src/wiring/createExtensionBlueprint.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ApiHolder, AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport {\n ExtensionAttachToSpec,\n ExtensionDefinition,\n ResolvedExtensionInputs,\n VerifyExtensionFactoryOutput,\n createExtension,\n ctxParamsSymbol,\n} from './createExtension';\nimport { z } from 'zod';\nimport { ExtensionInput } from './createExtensionInput';\nimport {\n AnyExtensionDataRef,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { createExtensionDataContainer } from '@internal/frontend';\nimport {\n ResolveInputValueOverrides,\n resolveInputOverrides,\n} from './resolveInputOverrides';\nimport { ExtensionDataContainer } from './types';\n\n/**\n * @public\n */\nexport type CreateExtensionBlueprintOptions<\n TKind extends string,\n TName extends string | undefined,\n TParams,\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n TDataRefs extends { [name in string]: AnyExtensionDataRef },\n> = {\n kind: TKind;\n attachTo: ExtensionAttachToSpec;\n disabled?: boolean;\n inputs?: TInputs;\n output: Array<UOutput>;\n name?: TName;\n config?: {\n schema: TConfigSchema;\n };\n factory(\n params: TParams,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n\n dataRefs?: TDataRefs;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport type ExtensionBlueprintParameters = {\n kind: string;\n name?: string;\n params?: object;\n configInput?: { [K in string]: any };\n config?: { [K in string]: any };\n output?: AnyExtensionDataRef;\n inputs?: {\n [KName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n };\n dataRefs?: { [name in string]: AnyExtensionDataRef };\n};\n\n/**\n * @public\n */\nexport interface ExtensionBlueprint<\n T extends ExtensionBlueprintParameters = ExtensionBlueprintParameters,\n> {\n dataRefs: T['dataRefs'];\n\n make<TNewName extends string | undefined>(args: {\n name?: TNewName;\n attachTo?: ExtensionAttachToSpec;\n disabled?: boolean;\n params: T['params'];\n }): ExtensionDefinition<{\n kind: T['kind'];\n name: string | undefined extends TNewName ? T['name'] : TNewName;\n config: T['config'];\n configInput: T['configInput'];\n output: T['output'];\n inputs: T['inputs'];\n params: T['params'];\n }>;\n\n /**\n * Creates a new extension from the blueprint.\n *\n * You must either pass `params` directly, or define a `factory` that can\n * optionally call the original factory with the same params.\n */\n makeWithOverrides<\n TNewName extends string | undefined,\n TExtensionConfigSchema extends {\n [key in string]: (zImpl: typeof z) => z.ZodType;\n },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends AnyExtensionDataRef,\n TExtraInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n >(args: {\n name?: TNewName;\n attachTo?: ExtensionAttachToSpec;\n disabled?: boolean;\n inputs?: TExtraInputs & {\n [KName in keyof T['inputs']]?: `Error: Input '${KName &\n string}' is already defined in parent definition`;\n };\n output?: Array<UNewOutput>;\n config?: {\n schema: TExtensionConfigSchema & {\n [KName in keyof T['config']]?: `Error: Config key '${KName &\n string}' is already defined in parent schema`;\n };\n };\n factory(\n originalFactory: (\n params: T['params'],\n context?: {\n config?: T['config'];\n inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;\n },\n ) => ExtensionDataContainer<NonNullable<T['output']>>,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: T['config'] & {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;\n },\n ): Iterable<UFactoryOutput> &\n VerifyExtensionFactoryOutput<\n AnyExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UFactoryOutput\n >;\n }): ExtensionDefinition<{\n config: (string extends keyof TExtensionConfigSchema\n ? {}\n : {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n }) &\n T['config'];\n configInput: (string extends keyof TExtensionConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TExtensionConfigSchema]: ReturnType<\n TExtensionConfigSchema[key]\n >;\n }>\n >) &\n T['configInput'];\n output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;\n inputs: T['inputs'] & TExtraInputs;\n kind: T['kind'];\n name: string | undefined extends TNewName ? T['name'] : TNewName;\n params: T['params'];\n }>;\n}\n\n/**\n * A simpler replacement for wrapping up `createExtension` inside a kind or type. This allows for a cleaner API for creating\n * types and instances of those types.\n *\n * @public\n */\nexport function createExtensionBlueprint<\n TParams extends object,\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n TKind extends string,\n TName extends string | undefined = undefined,\n TDataRefs extends { [name in string]: AnyExtensionDataRef } = never,\n>(\n options: CreateExtensionBlueprintOptions<\n TKind,\n TName,\n TParams,\n UOutput,\n TInputs,\n TConfigSchema,\n UFactoryOutput,\n TDataRefs\n >,\n): ExtensionBlueprint<{\n kind: TKind;\n name: TName;\n params: TParams;\n output: UOutput;\n inputs: string extends keyof TInputs ? {} : TInputs;\n config: string extends keyof TConfigSchema\n ? {}\n : { [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>> };\n configInput: string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >;\n dataRefs: TDataRefs;\n}> {\n return {\n dataRefs: options.dataRefs,\n make(args) {\n return createExtension({\n kind: options.kind,\n name: args.name ?? options.name,\n attachTo: args.attachTo ?? options.attachTo,\n disabled: args.disabled ?? options.disabled,\n inputs: options.inputs,\n output: options.output as AnyExtensionDataRef[],\n config: options.config,\n factory: ctx =>\n options.factory(\n { ...args.params, ...(ctx as any)[ctxParamsSymbol] },\n ctx,\n ) as Iterable<ExtensionDataValue<any, any>>,\n }) as ExtensionDefinition;\n },\n makeWithOverrides(args) {\n return createExtension({\n kind: options.kind,\n name: args.name ?? options.name,\n attachTo: args.attachTo ?? options.attachTo,\n disabled: args.disabled ?? options.disabled,\n inputs: { ...args.inputs, ...options.inputs },\n output: (args.output ?? options.output) as AnyExtensionDataRef[],\n config:\n options.config || args.config\n ? {\n schema: {\n ...options.config?.schema,\n ...args.config?.schema,\n },\n }\n : undefined,\n factory: ctx => {\n const { node, config, inputs, apis } = ctx;\n return args.factory(\n (innerParams, innerContext) => {\n return createExtensionDataContainer<UOutput>(\n options.factory(\n { ...innerParams, ...(ctx as any)[ctxParamsSymbol] },\n {\n apis,\n node,\n config: (innerContext?.config ?? config) as any,\n inputs: resolveInputOverrides(\n options.inputs,\n inputs,\n innerContext?.inputs,\n ) as any,\n },\n ) as Iterable<any>,\n options.output,\n );\n },\n {\n apis,\n node,\n config: config as any,\n inputs: inputs as any,\n },\n ) as Iterable<ExtensionDataValue<any, any>>;\n },\n }) as ExtensionDefinition;\n },\n } as ExtensionBlueprint<{\n kind: TKind;\n name: TName;\n params: TParams;\n output: UOutput;\n inputs: string extends keyof TInputs ? {} : TInputs;\n config: string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n };\n configInput: string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >;\n dataRefs: TDataRefs;\n }>;\n}\n"],"names":[],"mappings":";;;;AAqNO,SAAS,yBAed,OA2BC,EAAA;AACD,EAAO,OAAA;AAAA,IACL,UAAU,OAAQ,CAAA,QAAA;AAAA,IAClB,KAAK,IAAM,EAAA;AACT,MAAA,OAAO,eAAgB,CAAA;AAAA,QACrB,MAAM,OAAQ,CAAA,IAAA;AAAA,QACd,IAAA,EAAM,IAAK,CAAA,IAAA,IAAQ,OAAQ,CAAA,IAAA;AAAA,QAC3B,QAAA,EAAU,IAAK,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QACnC,QAAA,EAAU,IAAK,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QACnC,QAAQ,OAAQ,CAAA,MAAA;AAAA,QAChB,QAAQ,OAAQ,CAAA,MAAA;AAAA,QAChB,QAAQ,OAAQ,CAAA,MAAA;AAAA,QAChB,OAAA,EAAS,SACP,OAAQ,CAAA,OAAA;AAAA,UACN,EAAE,GAAG,IAAA,CAAK,QAAQ,GAAI,GAAA,CAAY,eAAe,CAAE,EAAA;AAAA,UACnD;AAAA;AACF,OACH,CAAA;AAAA,KACH;AAAA,IACA,kBAAkB,IAAM,EAAA;AACtB,MAAA,OAAO,eAAgB,CAAA;AAAA,QACrB,MAAM,OAAQ,CAAA,IAAA;AAAA,QACd,IAAA,EAAM,IAAK,CAAA,IAAA,IAAQ,OAAQ,CAAA,IAAA;AAAA,QAC3B,QAAA,EAAU,IAAK,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QACnC,QAAA,EAAU,IAAK,CAAA,QAAA,IAAY,OAAQ,CAAA,QAAA;AAAA,QACnC,QAAQ,EAAE,GAAG,KAAK,MAAQ,EAAA,GAAG,QAAQ,MAAO,EAAA;AAAA,QAC5C,MAAA,EAAS,IAAK,CAAA,MAAA,IAAU,OAAQ,CAAA,MAAA;AAAA,QAChC,MACE,EAAA,OAAA,CAAQ,MAAU,IAAA,IAAA,CAAK,MACnB,GAAA;AAAA,UACE,MAAQ,EAAA;AAAA,YACN,GAAG,QAAQ,MAAQ,EAAA,MAAA;AAAA,YACnB,GAAG,KAAK,MAAQ,EAAA;AAAA;AAClB,SAEF,GAAA,KAAA,CAAA;AAAA,QACN,SAAS,CAAO,GAAA,KAAA;AACd,UAAA,MAAM,EAAE,IAAA,EAAM,MAAQ,EAAA,MAAA,EAAQ,MAAS,GAAA,GAAA;AACvC,UAAA,OAAO,IAAK,CAAA,OAAA;AAAA,YACV,CAAC,aAAa,YAAiB,KAAA;AAC7B,cAAO,OAAA,4BAAA;AAAA,gBACL,OAAQ,CAAA,OAAA;AAAA,kBACN,EAAE,GAAG,WAAA,EAAa,GAAI,GAAA,CAAY,eAAe,CAAE,EAAA;AAAA,kBACnD;AAAA,oBACE,IAAA;AAAA,oBACA,IAAA;AAAA,oBACA,MAAA,EAAS,cAAc,MAAU,IAAA,MAAA;AAAA,oBACjC,MAAQ,EAAA,qBAAA;AAAA,sBACN,OAAQ,CAAA,MAAA;AAAA,sBACR,MAAA;AAAA,sBACA,YAAc,EAAA;AAAA;AAChB;AACF,iBACF;AAAA,gBACA,OAAQ,CAAA;AAAA,eACV;AAAA,aACF;AAAA,YACA;AAAA,cACE,IAAA;AAAA,cACA,IAAA;AAAA,cACA,MAAA;AAAA,cACA;AAAA;AACF,WACF;AAAA;AACF,OACD,CAAA;AAAA;AACH,GACF;AAoBF;;;;"}
@@ -1,4 +1,4 @@
1
- function createExtensionDataRef(id) {
1
+ function createExtensionDataRef() {
2
2
  const createRef = (refId) => Object.assign(
3
3
  (value) => ({
4
4
  $$type: "@backstage/ExtensionDataValue",
@@ -21,9 +21,6 @@ function createExtensionDataRef(id) {
21
21
  }
22
22
  }
23
23
  );
24
- if (id) {
25
- return createRef(id);
26
- }
27
24
  return {
28
25
  with(options) {
29
26
  return createRef(options.id);
@@ -1 +1 @@
1
- {"version":3,"file":"createExtensionDataRef.esm.js","sources":["../../src/wiring/createExtensionDataRef.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/** @public */\nexport type ExtensionDataValue<TData, TId extends string> = {\n readonly $$type: '@backstage/ExtensionDataValue';\n readonly id: TId;\n readonly value: TData;\n};\n\n/** @public */\nexport type ExtensionDataRef<\n TData,\n TId extends string = string,\n TConfig extends { optional?: true } = {},\n> = {\n readonly $$type: '@backstage/ExtensionDataRef';\n readonly id: TId;\n readonly T: TData;\n readonly config: TConfig;\n};\n\n/** @public */\nexport type ExtensionDataRefToValue<TDataRef extends AnyExtensionDataRef> =\n TDataRef extends ExtensionDataRef<infer IData, infer IId, any>\n ? ExtensionDataValue<IData, IId>\n : never;\n\n/** @public */\nexport type AnyExtensionDataRef = ExtensionDataRef<\n unknown,\n string,\n { optional?: true }\n>;\n\n/** @public */\nexport interface ConfigurableExtensionDataRef<\n TData,\n TId extends string,\n TConfig extends { optional?: true } = {},\n> extends ExtensionDataRef<TData, TId, TConfig> {\n optional(): ConfigurableExtensionDataRef<\n TData,\n TId,\n TConfig & { optional: true }\n >;\n (t: TData): ExtensionDataValue<TData, TId>;\n}\n\n/**\n * @public\n * @deprecated Use the following form instead: `createExtensionDataRef<Type>().with({ id: 'core.foo' })`\n */\nexport function createExtensionDataRef<TData>(\n id: string,\n): ConfigurableExtensionDataRef<TData, string>;\n/** @public */\nexport function createExtensionDataRef<TData>(): {\n with<TId extends string>(options: {\n id: TId;\n }): ConfigurableExtensionDataRef<TData, TId>;\n};\nexport function createExtensionDataRef<TData>(id?: string):\n | ConfigurableExtensionDataRef<TData, string>\n | {\n with<TId extends string>(options: {\n id: TId;\n }): ConfigurableExtensionDataRef<TData, TId>;\n } {\n const createRef = <TId extends string>(refId: TId) =>\n Object.assign(\n (value: TData): ExtensionDataValue<TData, TId> => ({\n $$type: '@backstage/ExtensionDataValue',\n id: refId,\n value,\n }),\n {\n id: refId,\n $$type: '@backstage/ExtensionDataRef',\n config: {},\n optional() {\n return {\n ...this,\n config: { ...this.config, optional: true },\n };\n },\n toString() {\n const optional = Boolean(this.config.optional);\n return `ExtensionDataRef{id=${refId},optional=${optional}}`;\n },\n } as ConfigurableExtensionDataRef<TData, TId, { optional?: true }>,\n );\n if (id) {\n return createRef(id);\n }\n return {\n with<TId extends string>(options: { id: TId }) {\n return createRef(options.id);\n },\n };\n}\n"],"names":[],"mappings":"AA2EO,SAAS,uBAA8B,EAMxC,EAAA;AACJ,EAAM,MAAA,SAAA,GAAY,CAAqB,KAAA,KACrC,MAAO,CAAA,MAAA;AAAA,IACL,CAAC,KAAkD,MAAA;AAAA,MACjD,MAAQ,EAAA,+BAAA;AAAA,MACR,EAAI,EAAA,KAAA;AAAA,MACJ;AAAA,KACF,CAAA;AAAA,IACA;AAAA,MACE,EAAI,EAAA,KAAA;AAAA,MACJ,MAAQ,EAAA,6BAAA;AAAA,MACR,QAAQ,EAAC;AAAA,MACT,QAAW,GAAA;AACT,QAAO,OAAA;AAAA,UACL,GAAG,IAAA;AAAA,UACH,QAAQ,EAAE,GAAG,IAAK,CAAA,MAAA,EAAQ,UAAU,IAAK;AAAA,SAC3C;AAAA,OACF;AAAA,MACA,QAAW,GAAA;AACT,QAAA,MAAM,QAAW,GAAA,OAAA,CAAQ,IAAK,CAAA,MAAA,CAAO,QAAQ,CAAA;AAC7C,QAAO,OAAA,CAAA,oBAAA,EAAuB,KAAK,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAA,CAAA;AAAA;AAC1D;AACF,GACF;AACF,EAAA,IAAI,EAAI,EAAA;AACN,IAAA,OAAO,UAAU,EAAE,CAAA;AAAA;AAErB,EAAO,OAAA;AAAA,IACL,KAAyB,OAAsB,EAAA;AAC7C,MAAO,OAAA,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA;AAC7B,GACF;AACF;;;;"}
1
+ {"version":3,"file":"createExtensionDataRef.esm.js","sources":["../../src/wiring/createExtensionDataRef.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/** @public */\nexport type ExtensionDataValue<TData, TId extends string> = {\n readonly $$type: '@backstage/ExtensionDataValue';\n readonly id: TId;\n readonly value: TData;\n};\n\n/** @public */\nexport type ExtensionDataRef<\n TData,\n TId extends string = string,\n TConfig extends { optional?: true } = {},\n> = {\n readonly $$type: '@backstage/ExtensionDataRef';\n readonly id: TId;\n readonly T: TData;\n readonly config: TConfig;\n};\n\n/** @public */\nexport type ExtensionDataRefToValue<TDataRef extends AnyExtensionDataRef> =\n TDataRef extends ExtensionDataRef<infer IData, infer IId, any>\n ? ExtensionDataValue<IData, IId>\n : never;\n\n/** @public */\nexport type AnyExtensionDataRef = ExtensionDataRef<\n unknown,\n string,\n { optional?: true }\n>;\n\n/** @public */\nexport interface ConfigurableExtensionDataRef<\n TData,\n TId extends string,\n TConfig extends { optional?: true } = {},\n> extends ExtensionDataRef<TData, TId, TConfig> {\n optional(): ConfigurableExtensionDataRef<\n TData,\n TId,\n TConfig & { optional: true }\n >;\n (t: TData): ExtensionDataValue<TData, TId>;\n}\n\n/** @public */\nexport function createExtensionDataRef<TData>(): {\n with<TId extends string>(options: {\n id: TId;\n }): ConfigurableExtensionDataRef<TData, TId>;\n} {\n const createRef = <TId extends string>(refId: TId) =>\n Object.assign(\n (value: TData): ExtensionDataValue<TData, TId> => ({\n $$type: '@backstage/ExtensionDataValue',\n id: refId,\n value,\n }),\n {\n id: refId,\n $$type: '@backstage/ExtensionDataRef',\n config: {},\n optional() {\n return {\n ...this,\n config: { ...this.config, optional: true },\n };\n },\n toString() {\n const optional = Boolean(this.config.optional);\n return `ExtensionDataRef{id=${refId},optional=${optional}}`;\n },\n } as ConfigurableExtensionDataRef<TData, TId, { optional?: true }>,\n );\n return {\n with<TId extends string>(options: { id: TId }) {\n return createRef(options.id);\n },\n };\n}\n"],"names":[],"mappings":"AA+DO,SAAS,sBAId,GAAA;AACA,EAAM,MAAA,SAAA,GAAY,CAAqB,KAAA,KACrC,MAAO,CAAA,MAAA;AAAA,IACL,CAAC,KAAkD,MAAA;AAAA,MACjD,MAAQ,EAAA,+BAAA;AAAA,MACR,EAAI,EAAA,KAAA;AAAA,MACJ;AAAA,KACF,CAAA;AAAA,IACA;AAAA,MACE,EAAI,EAAA,KAAA;AAAA,MACJ,MAAQ,EAAA,6BAAA;AAAA,MACR,QAAQ,EAAC;AAAA,MACT,QAAW,GAAA;AACT,QAAO,OAAA;AAAA,UACL,GAAG,IAAA;AAAA,UACH,QAAQ,EAAE,GAAG,IAAK,CAAA,MAAA,EAAQ,UAAU,IAAK;AAAA,SAC3C;AAAA,OACF;AAAA,MACA,QAAW,GAAA;AACT,QAAA,MAAM,QAAW,GAAA,OAAA,CAAQ,IAAK,CAAA,MAAA,CAAO,QAAQ,CAAA;AAC7C,QAAO,OAAA,CAAA,oBAAA,EAAuB,KAAK,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAA,CAAA;AAAA;AAC1D;AACF,GACF;AACF,EAAO,OAAA;AAAA,IACL,KAAyB,OAAsB,EAAA;AAC7C,MAAO,OAAA,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA;AAC7B,GACF;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"createFrontendPlugin.esm.js","sources":["../../src/wiring/createFrontendPlugin.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n OpaqueExtensionDefinition,\n OpaqueFrontendPlugin,\n} from '@internal/frontend';\nimport { ExtensionDefinition } from './createExtension';\nimport {\n Extension,\n ResolveExtensionId,\n resolveExtensionDefinition,\n} from './resolveExtensionDefinition';\nimport { AnyExternalRoutes, AnyRoutes, FeatureFlagConfig } from './types';\n\n/** @public */\nexport interface FrontendPlugin<\n TRoutes extends AnyRoutes = AnyRoutes,\n TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,\n TExtensionMap extends { [id in string]: ExtensionDefinition } = {\n [id in string]: ExtensionDefinition;\n },\n> {\n readonly $$type: '@backstage/FrontendPlugin';\n readonly id: string;\n readonly routes: TRoutes;\n readonly externalRoutes: TExternalRoutes;\n getExtension<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];\n withOverrides(options: {\n extensions: Array<ExtensionDefinition>;\n }): FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;\n}\n\n/** @public */\nexport interface PluginOptions<\n TId extends string,\n TRoutes extends AnyRoutes,\n TExternalRoutes extends AnyExternalRoutes,\n TExtensions extends readonly ExtensionDefinition[],\n> {\n id: TId;\n routes?: TRoutes;\n externalRoutes?: TExternalRoutes;\n extensions?: TExtensions;\n featureFlags?: FeatureFlagConfig[];\n}\n\n/** @public */\nexport function createFrontendPlugin<\n TId extends string,\n TRoutes extends AnyRoutes = {},\n TExternalRoutes extends AnyExternalRoutes = {},\n TExtensions extends readonly ExtensionDefinition[] = [],\n>(\n options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,\n): FrontendPlugin<\n TRoutes,\n TExternalRoutes,\n {\n [KExtension in TExtensions[number] as ResolveExtensionId<\n KExtension,\n TId\n >]: KExtension;\n }\n> {\n const extensions = new Array<Extension<any>>();\n const extensionDefinitionsById = new Map<\n string,\n typeof OpaqueExtensionDefinition.TInternal\n >();\n\n for (const def of options.extensions ?? []) {\n const internal = OpaqueExtensionDefinition.toInternal(def);\n const ext = resolveExtensionDefinition(def, { namespace: options.id });\n extensions.push(ext);\n extensionDefinitionsById.set(ext.id, {\n ...internal,\n namespace: options.id,\n });\n }\n\n if (extensions.length !== extensionDefinitionsById.size) {\n const extensionIds = extensions.map(e => e.id);\n const duplicates = Array.from(\n new Set(\n extensionIds.filter((id, index) => extensionIds.indexOf(id) !== index),\n ),\n );\n // TODO(Rugvip): This could provide some more information about the kind + name of the extensions\n throw new Error(\n `Plugin '${options.id}' provided duplicate extensions: ${duplicates.join(\n ', ',\n )}`,\n );\n }\n\n return OpaqueFrontendPlugin.createInstance('v1', {\n id: options.id,\n routes: options.routes ?? ({} as TRoutes),\n externalRoutes: options.externalRoutes ?? ({} as TExternalRoutes),\n featureFlags: options.featureFlags ?? [],\n extensions: extensions,\n getExtension(id) {\n const ext = extensionDefinitionsById.get(id);\n if (!ext) {\n throw new Error(\n `Attempted to get non-existent extension '${id}' from plugin '${options.id}'`,\n );\n }\n return ext;\n },\n toString() {\n return `Plugin{id=${options.id}}`;\n },\n withOverrides(overrides) {\n const overriddenExtensionIds = new Set(\n overrides.extensions.map(\n e => resolveExtensionDefinition(e, { namespace: options.id }).id,\n ),\n );\n const nonOverriddenExtensions = (options.extensions ?? []).filter(\n e =>\n !overriddenExtensionIds.has(\n resolveExtensionDefinition(e, { namespace: options.id }).id,\n ),\n );\n return createFrontendPlugin({\n ...options,\n extensions: [...nonOverriddenExtensions, ...overrides.extensions],\n });\n },\n });\n}\n"],"names":[],"mappings":";;;;AA6DO,SAAS,qBAMd,OAUA,EAAA;AACA,EAAM,MAAA,UAAA,GAAa,IAAI,KAAsB,EAAA;AAC7C,EAAM,MAAA,wBAAA,uBAA+B,GAGnC,EAAA;AAEF,EAAA,KAAA,MAAW,GAAO,IAAA,OAAA,CAAQ,UAAc,IAAA,EAAI,EAAA;AAC1C,IAAM,MAAA,QAAA,GAAW,yBAA0B,CAAA,UAAA,CAAW,GAAG,CAAA;AACzD,IAAA,MAAM,MAAM,0BAA2B,CAAA,GAAA,EAAK,EAAE,SAAW,EAAA,OAAA,CAAQ,IAAI,CAAA;AACrE,IAAA,UAAA,CAAW,KAAK,GAAG,CAAA;AACnB,IAAyB,wBAAA,CAAA,GAAA,CAAI,IAAI,EAAI,EAAA;AAAA,MACnC,GAAG,QAAA;AAAA,MACH,WAAW,OAAQ,CAAA;AAAA,KACpB,CAAA;AAAA;AAGH,EAAI,IAAA,UAAA,CAAW,MAAW,KAAA,wBAAA,CAAyB,IAAM,EAAA;AACvD,IAAA,MAAM,YAAe,GAAA,UAAA,CAAW,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,EAAE,CAAA;AAC7C,IAAA,MAAM,aAAa,KAAM,CAAA,IAAA;AAAA,MACvB,IAAI,GAAA;AAAA,QACF,YAAA,CAAa,OAAO,CAAC,EAAA,EAAI,UAAU,YAAa,CAAA,OAAA,CAAQ,EAAE,CAAA,KAAM,KAAK;AAAA;AACvE,KACF;AAEA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAW,QAAA,EAAA,OAAA,CAAQ,EAAE,CAAA,iCAAA,EAAoC,UAAW,CAAA,IAAA;AAAA,QAClE;AAAA,OACD,CAAA;AAAA,KACH;AAAA;AAGF,EAAO,OAAA,oBAAA,CAAqB,eAAe,IAAM,EAAA;AAAA,IAC/C,IAAI,OAAQ,CAAA,EAAA;AAAA,IACZ,MAAA,EAAQ,OAAQ,CAAA,MAAA,IAAW,EAAC;AAAA,IAC5B,cAAA,EAAgB,OAAQ,CAAA,cAAA,IAAmB,EAAC;AAAA,IAC5C,YAAA,EAAc,OAAQ,CAAA,YAAA,IAAgB,EAAC;AAAA,IACvC,UAAA;AAAA,IACA,aAAa,EAAI,EAAA;AACf,MAAM,MAAA,GAAA,GAAM,wBAAyB,CAAA,GAAA,CAAI,EAAE,CAAA;AAC3C,MAAA,IAAI,CAAC,GAAK,EAAA;AACR,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAA4C,yCAAA,EAAA,EAAE,CAAkB,eAAA,EAAA,OAAA,CAAQ,EAAE,CAAA,CAAA;AAAA,SAC5E;AAAA;AAEF,MAAO,OAAA,GAAA;AAAA,KACT;AAAA,IACA,QAAW,GAAA;AACT,MAAO,OAAA,CAAA,UAAA,EAAa,QAAQ,EAAE,CAAA,CAAA,CAAA;AAAA,KAChC;AAAA,IACA,cAAc,SAAW,EAAA;AACvB,MAAA,MAAM,yBAAyB,IAAI,GAAA;AAAA,QACjC,UAAU,UAAW,CAAA,GAAA;AAAA,UACnB,CAAA,CAAA,KAAK,2BAA2B,CAAG,EAAA,EAAE,WAAW,OAAQ,CAAA,EAAA,EAAI,CAAE,CAAA;AAAA;AAChE,OACF;AACA,MAAA,MAAM,uBAA2B,GAAA,CAAA,OAAA,CAAQ,UAAc,IAAA,EAAI,EAAA,MAAA;AAAA,QACzD,CAAA,CAAA,KACE,CAAC,sBAAuB,CAAA,GAAA;AAAA,UACtB,2BAA2B,CAAG,EAAA,EAAE,WAAW,OAAQ,CAAA,EAAA,EAAI,CAAE,CAAA;AAAA;AAC3D,OACJ;AACA,MAAA,OAAO,oBAAqB,CAAA;AAAA,QAC1B,GAAG,OAAA;AAAA,QACH,YAAY,CAAC,GAAG,uBAAyB,EAAA,GAAG,UAAU,UAAU;AAAA,OACjE,CAAA;AAAA;AACH,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"createFrontendPlugin.esm.js","sources":["../../src/wiring/createFrontendPlugin.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n OpaqueExtensionDefinition,\n OpaqueFrontendPlugin,\n} from '@internal/frontend';\nimport { ExtensionDefinition } from './createExtension';\nimport {\n Extension,\n resolveExtensionDefinition,\n} from './resolveExtensionDefinition';\nimport { AnyExternalRoutes, AnyRoutes, FeatureFlagConfig } from './types';\nimport { MakeSortedExtensionsMap } from './MakeSortedExtensionsMap';\n\n/** @public */\nexport interface FrontendPlugin<\n TRoutes extends AnyRoutes = AnyRoutes,\n TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,\n TExtensionMap extends { [id in string]: ExtensionDefinition } = {\n [id in string]: ExtensionDefinition;\n },\n> {\n readonly $$type: '@backstage/FrontendPlugin';\n readonly id: string;\n readonly routes: TRoutes;\n readonly externalRoutes: TExternalRoutes;\n getExtension<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];\n withOverrides(options: {\n extensions: Array<ExtensionDefinition>;\n }): FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;\n}\n\n/** @public */\nexport interface PluginOptions<\n TId extends string,\n TRoutes extends AnyRoutes,\n TExternalRoutes extends AnyExternalRoutes,\n TExtensions extends readonly ExtensionDefinition[],\n> {\n id: TId;\n routes?: TRoutes;\n externalRoutes?: TExternalRoutes;\n extensions?: TExtensions;\n featureFlags?: FeatureFlagConfig[];\n}\n\n/** @public */\nexport function createFrontendPlugin<\n TId extends string,\n TRoutes extends AnyRoutes = {},\n TExternalRoutes extends AnyExternalRoutes = {},\n TExtensions extends readonly ExtensionDefinition[] = [],\n>(\n options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,\n): FrontendPlugin<\n TRoutes,\n TExternalRoutes,\n MakeSortedExtensionsMap<TExtensions[number], TId>\n> {\n const extensions = new Array<Extension<any>>();\n const extensionDefinitionsById = new Map<\n string,\n typeof OpaqueExtensionDefinition.TInternal\n >();\n\n for (const def of options.extensions ?? []) {\n const internal = OpaqueExtensionDefinition.toInternal(def);\n const ext = resolveExtensionDefinition(def, { namespace: options.id });\n extensions.push(ext);\n extensionDefinitionsById.set(ext.id, {\n ...internal,\n namespace: options.id,\n });\n }\n\n if (extensions.length !== extensionDefinitionsById.size) {\n const extensionIds = extensions.map(e => e.id);\n const duplicates = Array.from(\n new Set(\n extensionIds.filter((id, index) => extensionIds.indexOf(id) !== index),\n ),\n );\n // TODO(Rugvip): This could provide some more information about the kind + name of the extensions\n throw new Error(\n `Plugin '${options.id}' provided duplicate extensions: ${duplicates.join(\n ', ',\n )}`,\n );\n }\n\n return OpaqueFrontendPlugin.createInstance('v1', {\n id: options.id,\n routes: options.routes ?? ({} as TRoutes),\n externalRoutes: options.externalRoutes ?? ({} as TExternalRoutes),\n featureFlags: options.featureFlags ?? [],\n extensions: extensions,\n getExtension(id) {\n const ext = extensionDefinitionsById.get(id);\n if (!ext) {\n throw new Error(\n `Attempted to get non-existent extension '${id}' from plugin '${options.id}'`,\n );\n }\n return ext;\n },\n toString() {\n return `Plugin{id=${options.id}}`;\n },\n withOverrides(overrides) {\n const overriddenExtensionIds = new Set(\n overrides.extensions.map(\n e => resolveExtensionDefinition(e, { namespace: options.id }).id,\n ),\n );\n const nonOverriddenExtensions = (options.extensions ?? []).filter(\n e =>\n !overriddenExtensionIds.has(\n resolveExtensionDefinition(e, { namespace: options.id }).id,\n ),\n );\n return createFrontendPlugin({\n ...options,\n extensions: [...nonOverriddenExtensions, ...overrides.extensions],\n });\n },\n });\n}\n"],"names":[],"mappings":";;;;AA6DO,SAAS,qBAMd,OAKA,EAAA;AACA,EAAM,MAAA,UAAA,GAAa,IAAI,KAAsB,EAAA;AAC7C,EAAM,MAAA,wBAAA,uBAA+B,GAGnC,EAAA;AAEF,EAAA,KAAA,MAAW,GAAO,IAAA,OAAA,CAAQ,UAAc,IAAA,EAAI,EAAA;AAC1C,IAAM,MAAA,QAAA,GAAW,yBAA0B,CAAA,UAAA,CAAW,GAAG,CAAA;AACzD,IAAA,MAAM,MAAM,0BAA2B,CAAA,GAAA,EAAK,EAAE,SAAW,EAAA,OAAA,CAAQ,IAAI,CAAA;AACrE,IAAA,UAAA,CAAW,KAAK,GAAG,CAAA;AACnB,IAAyB,wBAAA,CAAA,GAAA,CAAI,IAAI,EAAI,EAAA;AAAA,MACnC,GAAG,QAAA;AAAA,MACH,WAAW,OAAQ,CAAA;AAAA,KACpB,CAAA;AAAA;AAGH,EAAI,IAAA,UAAA,CAAW,MAAW,KAAA,wBAAA,CAAyB,IAAM,EAAA;AACvD,IAAA,MAAM,YAAe,GAAA,UAAA,CAAW,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,EAAE,CAAA;AAC7C,IAAA,MAAM,aAAa,KAAM,CAAA,IAAA;AAAA,MACvB,IAAI,GAAA;AAAA,QACF,YAAA,CAAa,OAAO,CAAC,EAAA,EAAI,UAAU,YAAa,CAAA,OAAA,CAAQ,EAAE,CAAA,KAAM,KAAK;AAAA;AACvE,KACF;AAEA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAW,QAAA,EAAA,OAAA,CAAQ,EAAE,CAAA,iCAAA,EAAoC,UAAW,CAAA,IAAA;AAAA,QAClE;AAAA,OACD,CAAA;AAAA,KACH;AAAA;AAGF,EAAO,OAAA,oBAAA,CAAqB,eAAe,IAAM,EAAA;AAAA,IAC/C,IAAI,OAAQ,CAAA,EAAA;AAAA,IACZ,MAAA,EAAQ,OAAQ,CAAA,MAAA,IAAW,EAAC;AAAA,IAC5B,cAAA,EAAgB,OAAQ,CAAA,cAAA,IAAmB,EAAC;AAAA,IAC5C,YAAA,EAAc,OAAQ,CAAA,YAAA,IAAgB,EAAC;AAAA,IACvC,UAAA;AAAA,IACA,aAAa,EAAI,EAAA;AACf,MAAM,MAAA,GAAA,GAAM,wBAAyB,CAAA,GAAA,CAAI,EAAE,CAAA;AAC3C,MAAA,IAAI,CAAC,GAAK,EAAA;AACR,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAA4C,yCAAA,EAAA,EAAE,CAAkB,eAAA,EAAA,OAAA,CAAQ,EAAE,CAAA,CAAA;AAAA,SAC5E;AAAA;AAEF,MAAO,OAAA,GAAA;AAAA,KACT;AAAA,IACA,QAAW,GAAA;AACT,MAAO,OAAA,CAAA,UAAA,EAAa,QAAQ,EAAE,CAAA,CAAA,CAAA;AAAA,KAChC;AAAA,IACA,cAAc,SAAW,EAAA;AACvB,MAAA,MAAM,yBAAyB,IAAI,GAAA;AAAA,QACjC,UAAU,UAAW,CAAA,GAAA;AAAA,UACnB,CAAA,CAAA,KAAK,2BAA2B,CAAG,EAAA,EAAE,WAAW,OAAQ,CAAA,EAAA,EAAI,CAAE,CAAA;AAAA;AAChE,OACF;AACA,MAAA,MAAM,uBAA2B,GAAA,CAAA,OAAA,CAAQ,UAAc,IAAA,EAAI,EAAA,MAAA;AAAA,QACzD,CAAA,CAAA,KACE,CAAC,sBAAuB,CAAA,GAAA;AAAA,UACtB,2BAA2B,CAAG,EAAA,EAAE,WAAW,OAAQ,CAAA,EAAA,EAAI,CAAE,CAAA;AAAA;AAC3D,OACJ;AACA,MAAA,OAAO,oBAAqB,CAAA;AAAA,QAC1B,GAAG,OAAA;AAAA,QACH,YAAY,CAAC,GAAG,uBAAyB,EAAA,GAAG,UAAU,UAAU;AAAA,OACjE,CAAA;AAAA;AACH,GACD,CAAA;AACH;;;;"}
@@ -1,4 +1,6 @@
1
- import { createExtensionDataContainer } from './createExtensionDataContainer.esm.js';
1
+ import { createExtensionDataContainer } from '../frontend-internal/src/wiring/createExtensionDataContainer.esm.js';
2
+ import '../frontend-internal/src/wiring/InternalExtensionDefinition.esm.js';
3
+ import '../frontend-internal/src/wiring/InternalFrontendPlugin.esm.js';
2
4
 
3
5
  function expectArray(value) {
4
6
  return value;
@@ -1 +1 @@
1
- {"version":3,"file":"resolveInputOverrides.esm.js","sources":["../../src/wiring/resolveInputOverrides.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport { ResolvedExtensionInput } from './createExtension';\nimport {\n ExtensionDataContainer,\n createExtensionDataContainer,\n} from './createExtensionDataContainer';\nimport {\n AnyExtensionDataRef,\n ExtensionDataRefToValue,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\n\n/** @public */\nexport type ResolveInputValueOverrides<\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n } = {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n> = Expand<\n {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n }\n >\n ? IOptional extends true\n ? never\n : KName\n : never]: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n { optional: boolean; singleton: infer ISingleton extends boolean }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n } & {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n }\n >\n ? IOptional extends true\n ? KName\n : never\n : never]?: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n { optional: boolean; singleton: infer ISingleton extends boolean }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n }\n>;\n\nfunction expectArray<T>(value: T | T[]): T[] {\n return value as T[];\n}\nfunction expectItem<T>(value: T | T[]): T {\n return value as T;\n}\n\n/** @internal */\nexport function resolveInputOverrides(\n declaredInputs?: {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n inputs?: {\n [KName in string]?:\n | ({ node: AppNode } & ExtensionDataContainer<any>)\n | Array<{ node: AppNode } & ExtensionDataContainer<any>>;\n },\n inputOverrides?: ResolveInputValueOverrides,\n) {\n if (!declaredInputs || !inputs || !inputOverrides) {\n return inputs;\n }\n\n const newInputs: typeof inputs = {};\n for (const name in declaredInputs) {\n if (!Object.hasOwn(declaredInputs, name)) {\n continue;\n }\n const declaredInput = declaredInputs[name];\n const providedData = inputOverrides[name];\n if (declaredInput.config.singleton) {\n const originalInput = expectItem(inputs[name]);\n if (providedData) {\n const providedContainer = createExtensionDataContainer(\n providedData as Iterable<ExtensionDataValue<any, any>>,\n declaredInput.extensionData,\n );\n if (!originalInput) {\n throw new Error(\n `attempted to override data of input '${name}' but it is not present in the original inputs`,\n );\n }\n newInputs[name] = Object.assign(providedContainer, {\n node: (originalInput as ResolvedExtensionInput<any>).node,\n }) as any;\n }\n } else {\n const originalInput = expectArray(inputs[name]);\n if (!Array.isArray(providedData)) {\n throw new Error(\n `override data provided for input '${name}' must be an array`,\n );\n }\n\n // Regular inputs can be overridden in two different ways:\n // 1) Forward a subset of the original inputs in a new order\n // 2) Provide new data for each original input\n\n // First check if all inputs are being removed\n if (providedData.length === 0) {\n newInputs[name] = [];\n } else {\n // Check how many of the provided data items have a node property, i.e. is a forwarded input\n const withNodesCount = providedData.filter(d => 'node' in d).length;\n if (withNodesCount === 0) {\n if (originalInput.length !== providedData.length) {\n throw new Error(\n `override data provided for input '${name}' must match the length of the original inputs`,\n );\n }\n newInputs[name] = providedData.map((data, i) => {\n const providedContainer = createExtensionDataContainer(\n data as Iterable<ExtensionDataValue<any, any>>,\n declaredInput.extensionData,\n );\n return Object.assign(providedContainer, {\n node: (originalInput[i] as ResolvedExtensionInput<any>).node,\n }) as any;\n });\n } else if (withNodesCount === providedData.length) {\n newInputs[name] = providedData as any;\n } else {\n throw new Error(\n `override data for input '${name}' may not mix forwarded inputs with data overrides`,\n );\n }\n }\n }\n }\n return newInputs;\n}\n"],"names":[],"mappings":";;AAqFA,SAAS,YAAe,KAAqB,EAAA;AAC3C,EAAO,OAAA,KAAA;AACT;AACA,SAAS,WAAc,KAAmB,EAAA;AACxC,EAAO,OAAA,KAAA;AACT;AAGgB,SAAA,qBAAA,CACd,cAMA,EAAA,MAAA,EAKA,cACA,EAAA;AACA,EAAA,IAAI,CAAC,cAAA,IAAkB,CAAC,MAAA,IAAU,CAAC,cAAgB,EAAA;AACjD,IAAO,OAAA,MAAA;AAAA;AAGT,EAAA,MAAM,YAA2B,EAAC;AAClC,EAAA,KAAA,MAAW,QAAQ,cAAgB,EAAA;AACjC,IAAA,IAAI,CAAC,MAAA,CAAO,MAAO,CAAA,cAAA,EAAgB,IAAI,CAAG,EAAA;AACxC,MAAA;AAAA;AAEF,IAAM,MAAA,aAAA,GAAgB,eAAe,IAAI,CAAA;AACzC,IAAM,MAAA,YAAA,GAAe,eAAe,IAAI,CAAA;AACxC,IAAI,IAAA,aAAA,CAAc,OAAO,SAAW,EAAA;AAClC,MAAA,MAAM,aAAgB,GAAA,UAAA,CAAW,MAAO,CAAA,IAAI,CAAC,CAAA;AAC7C,MAAA,IAAI,YAAc,EAAA;AAChB,QAAA,MAAM,iBAAoB,GAAA,4BAAA;AAAA,UACxB,YAAA;AAAA,UACA,aAAc,CAAA;AAAA,SAChB;AACA,QAAA,IAAI,CAAC,aAAe,EAAA;AAClB,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,wCAAwC,IAAI,CAAA,8CAAA;AAAA,WAC9C;AAAA;AAEF,QAAA,SAAA,CAAU,IAAI,CAAA,GAAI,MAAO,CAAA,MAAA,CAAO,iBAAmB,EAAA;AAAA,UACjD,MAAO,aAA8C,CAAA;AAAA,SACtD,CAAA;AAAA;AACH,KACK,MAAA;AACL,MAAA,MAAM,aAAgB,GAAA,WAAA,CAAY,MAAO,CAAA,IAAI,CAAC,CAAA;AAC9C,MAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,YAAY,CAAG,EAAA;AAChC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,qCAAqC,IAAI,CAAA,kBAAA;AAAA,SAC3C;AAAA;AAQF,MAAI,IAAA,YAAA,CAAa,WAAW,CAAG,EAAA;AAC7B,QAAU,SAAA,CAAA,IAAI,IAAI,EAAC;AAAA,OACd,MAAA;AAEL,QAAA,MAAM,iBAAiB,YAAa,CAAA,MAAA,CAAO,CAAK,CAAA,KAAA,MAAA,IAAU,CAAC,CAAE,CAAA,MAAA;AAC7D,QAAA,IAAI,mBAAmB,CAAG,EAAA;AACxB,UAAI,IAAA,aAAA,CAAc,MAAW,KAAA,YAAA,CAAa,MAAQ,EAAA;AAChD,YAAA,MAAM,IAAI,KAAA;AAAA,cACR,qCAAqC,IAAI,CAAA,8CAAA;AAAA,aAC3C;AAAA;AAEF,UAAA,SAAA,CAAU,IAAI,CAAI,GAAA,YAAA,CAAa,GAAI,CAAA,CAAC,MAAM,CAAM,KAAA;AAC9C,YAAA,MAAM,iBAAoB,GAAA,4BAAA;AAAA,cACxB,IAAA;AAAA,cACA,aAAc,CAAA;AAAA,aAChB;AACA,YAAO,OAAA,MAAA,CAAO,OAAO,iBAAmB,EAAA;AAAA,cACtC,IAAA,EAAO,aAAc,CAAA,CAAC,CAAkC,CAAA;AAAA,aACzD,CAAA;AAAA,WACF,CAAA;AAAA,SACH,MAAA,IAAW,cAAmB,KAAA,YAAA,CAAa,MAAQ,EAAA;AACjD,UAAA,SAAA,CAAU,IAAI,CAAI,GAAA,YAAA;AAAA,SACb,MAAA;AACL,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,4BAA4B,IAAI,CAAA,kDAAA;AAAA,WAClC;AAAA;AACF;AACF;AACF;AAEF,EAAO,OAAA,SAAA;AACT;;;;"}
1
+ {"version":3,"file":"resolveInputOverrides.esm.js","sources":["../../src/wiring/resolveInputOverrides.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport { ResolvedExtensionInput } from './createExtension';\nimport { createExtensionDataContainer } from '@internal/frontend';\nimport {\n AnyExtensionDataRef,\n ExtensionDataRefToValue,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\nimport { ExtensionDataContainer } from './types';\n\n/** @public */\nexport type ResolveInputValueOverrides<\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n } = {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n> = Expand<\n {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n }\n >\n ? IOptional extends true\n ? never\n : KName\n : never]: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n { optional: boolean; singleton: infer ISingleton extends boolean }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n } & {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n }\n >\n ? IOptional extends true\n ? KName\n : never\n : never]?: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n { optional: boolean; singleton: infer ISingleton extends boolean }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n }\n>;\n\nfunction expectArray<T>(value: T | T[]): T[] {\n return value as T[];\n}\nfunction expectItem<T>(value: T | T[]): T {\n return value as T;\n}\n\n/** @internal */\nexport function resolveInputOverrides(\n declaredInputs?: {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n inputs?: {\n [KName in string]?:\n | ({ node: AppNode } & ExtensionDataContainer<any>)\n | Array<{ node: AppNode } & ExtensionDataContainer<any>>;\n },\n inputOverrides?: ResolveInputValueOverrides,\n) {\n if (!declaredInputs || !inputs || !inputOverrides) {\n return inputs;\n }\n\n const newInputs: typeof inputs = {};\n for (const name in declaredInputs) {\n if (!Object.hasOwn(declaredInputs, name)) {\n continue;\n }\n const declaredInput = declaredInputs[name];\n const providedData = inputOverrides[name];\n if (declaredInput.config.singleton) {\n const originalInput = expectItem(inputs[name]);\n if (providedData) {\n const providedContainer = createExtensionDataContainer(\n providedData as Iterable<ExtensionDataValue<any, any>>,\n declaredInput.extensionData,\n );\n if (!originalInput) {\n throw new Error(\n `attempted to override data of input '${name}' but it is not present in the original inputs`,\n );\n }\n newInputs[name] = Object.assign(providedContainer, {\n node: (originalInput as ResolvedExtensionInput<any>).node,\n }) as any;\n }\n } else {\n const originalInput = expectArray(inputs[name]);\n if (!Array.isArray(providedData)) {\n throw new Error(\n `override data provided for input '${name}' must be an array`,\n );\n }\n\n // Regular inputs can be overridden in two different ways:\n // 1) Forward a subset of the original inputs in a new order\n // 2) Provide new data for each original input\n\n // First check if all inputs are being removed\n if (providedData.length === 0) {\n newInputs[name] = [];\n } else {\n // Check how many of the provided data items have a node property, i.e. is a forwarded input\n const withNodesCount = providedData.filter(d => 'node' in d).length;\n if (withNodesCount === 0) {\n if (originalInput.length !== providedData.length) {\n throw new Error(\n `override data provided for input '${name}' must match the length of the original inputs`,\n );\n }\n newInputs[name] = providedData.map((data, i) => {\n const providedContainer = createExtensionDataContainer(\n data as Iterable<ExtensionDataValue<any, any>>,\n declaredInput.extensionData,\n );\n return Object.assign(providedContainer, {\n node: (originalInput[i] as ResolvedExtensionInput<any>).node,\n }) as any;\n });\n } else if (withNodesCount === providedData.length) {\n newInputs[name] = providedData as any;\n } else {\n throw new Error(\n `override data for input '${name}' may not mix forwarded inputs with data overrides`,\n );\n }\n }\n }\n }\n return newInputs;\n}\n"],"names":[],"mappings":";;;;AAmFA,SAAS,YAAe,KAAqB,EAAA;AAC3C,EAAO,OAAA,KAAA;AACT;AACA,SAAS,WAAc,KAAmB,EAAA;AACxC,EAAO,OAAA,KAAA;AACT;AAGgB,SAAA,qBAAA,CACd,cAMA,EAAA,MAAA,EAKA,cACA,EAAA;AACA,EAAA,IAAI,CAAC,cAAA,IAAkB,CAAC,MAAA,IAAU,CAAC,cAAgB,EAAA;AACjD,IAAO,OAAA,MAAA;AAAA;AAGT,EAAA,MAAM,YAA2B,EAAC;AAClC,EAAA,KAAA,MAAW,QAAQ,cAAgB,EAAA;AACjC,IAAA,IAAI,CAAC,MAAA,CAAO,MAAO,CAAA,cAAA,EAAgB,IAAI,CAAG,EAAA;AACxC,MAAA;AAAA;AAEF,IAAM,MAAA,aAAA,GAAgB,eAAe,IAAI,CAAA;AACzC,IAAM,MAAA,YAAA,GAAe,eAAe,IAAI,CAAA;AACxC,IAAI,IAAA,aAAA,CAAc,OAAO,SAAW,EAAA;AAClC,MAAA,MAAM,aAAgB,GAAA,UAAA,CAAW,MAAO,CAAA,IAAI,CAAC,CAAA;AAC7C,MAAA,IAAI,YAAc,EAAA;AAChB,QAAA,MAAM,iBAAoB,GAAA,4BAAA;AAAA,UACxB,YAAA;AAAA,UACA,aAAc,CAAA;AAAA,SAChB;AACA,QAAA,IAAI,CAAC,aAAe,EAAA;AAClB,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,wCAAwC,IAAI,CAAA,8CAAA;AAAA,WAC9C;AAAA;AAEF,QAAA,SAAA,CAAU,IAAI,CAAA,GAAI,MAAO,CAAA,MAAA,CAAO,iBAAmB,EAAA;AAAA,UACjD,MAAO,aAA8C,CAAA;AAAA,SACtD,CAAA;AAAA;AACH,KACK,MAAA;AACL,MAAA,MAAM,aAAgB,GAAA,WAAA,CAAY,MAAO,CAAA,IAAI,CAAC,CAAA;AAC9C,MAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,YAAY,CAAG,EAAA;AAChC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,qCAAqC,IAAI,CAAA,kBAAA;AAAA,SAC3C;AAAA;AAQF,MAAI,IAAA,YAAA,CAAa,WAAW,CAAG,EAAA;AAC7B,QAAU,SAAA,CAAA,IAAI,IAAI,EAAC;AAAA,OACd,MAAA;AAEL,QAAA,MAAM,iBAAiB,YAAa,CAAA,MAAA,CAAO,CAAK,CAAA,KAAA,MAAA,IAAU,CAAC,CAAE,CAAA,MAAA;AAC7D,QAAA,IAAI,mBAAmB,CAAG,EAAA;AACxB,UAAI,IAAA,aAAA,CAAc,MAAW,KAAA,YAAA,CAAa,MAAQ,EAAA;AAChD,YAAA,MAAM,IAAI,KAAA;AAAA,cACR,qCAAqC,IAAI,CAAA,8CAAA;AAAA,aAC3C;AAAA;AAEF,UAAA,SAAA,CAAU,IAAI,CAAI,GAAA,YAAA,CAAa,GAAI,CAAA,CAAC,MAAM,CAAM,KAAA;AAC9C,YAAA,MAAM,iBAAoB,GAAA,4BAAA;AAAA,cACxB,IAAA;AAAA,cACA,aAAc,CAAA;AAAA,aAChB;AACA,YAAO,OAAA,MAAA,CAAO,OAAO,iBAAmB,EAAA;AAAA,cACtC,IAAA,EAAO,aAAc,CAAA,CAAC,CAAkC,CAAA;AAAA,aACzD,CAAA;AAAA,WACF,CAAA;AAAA,SACH,MAAA,IAAW,cAAmB,KAAA,YAAA,CAAa,MAAQ,EAAA;AACjD,UAAA,SAAA,CAAU,IAAI,CAAI,GAAA,YAAA;AAAA,SACb,MAAA;AACL,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,4BAA4B,IAAI,CAAA,kDAAA;AAAA,WAClC;AAAA;AACF;AACF;AACF;AAEF,EAAO,OAAA,SAAA;AACT;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/frontend-plugin-api",
3
- "version": "0.9.6-next.0",
3
+ "version": "0.10.0-next.2",
4
4
  "backstage": {
5
5
  "role": "web-library"
6
6
  },
@@ -31,7 +31,7 @@
31
31
  "test": "backstage-cli package test"
32
32
  },
33
33
  "dependencies": {
34
- "@backstage/core-components": "0.16.4",
34
+ "@backstage/core-components": "0.16.5-next.1",
35
35
  "@backstage/core-plugin-api": "1.10.4",
36
36
  "@backstage/types": "1.2.1",
37
37
  "@backstage/version-bridge": "1.0.11",
@@ -41,10 +41,10 @@
41
41
  "zod-to-json-schema": "^3.21.4"
42
42
  },
43
43
  "devDependencies": {
44
- "@backstage/cli": "0.30.0",
45
- "@backstage/frontend-app-api": "0.10.6-next.0",
46
- "@backstage/frontend-test-utils": "0.2.7-next.0",
47
- "@backstage/test-utils": "1.7.5",
44
+ "@backstage/cli": "0.31.0-next.1",
45
+ "@backstage/frontend-app-api": "0.11.0-next.2",
46
+ "@backstage/frontend-test-utils": "0.3.0-next.2",
47
+ "@backstage/test-utils": "1.7.6-next.0",
48
48
  "@testing-library/jest-dom": "^6.0.0",
49
49
  "@testing-library/react": "^16.0.0",
50
50
  "@types/react": "^18.0.0",
@@ -64,12 +64,5 @@
64
64
  "optional": true
65
65
  }
66
66
  },
67
- "typesVersions": {
68
- "*": {
69
- "index": [
70
- "dist/index.d.ts"
71
- ]
72
- }
73
- },
74
67
  "module": "./dist/index.esm.js"
75
68
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"createExtensionDataContainer.esm.js","sources":["../../src/wiring/createExtensionDataContainer.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AnyExtensionDataRef,\n ExtensionDataRef,\n ExtensionDataValue,\n} from './createExtensionDataRef';\n\n/** @public */\nexport type ExtensionDataContainer<UExtensionData extends AnyExtensionDataRef> =\n Iterable<\n UExtensionData extends ExtensionDataRef<\n infer IData,\n infer IId,\n infer IConfig\n >\n ? IConfig['optional'] extends true\n ? never\n : ExtensionDataValue<IData, IId>\n : never\n > & {\n get<TId extends UExtensionData['id']>(\n ref: ExtensionDataRef<any, TId, any>,\n ): UExtensionData extends ExtensionDataRef<infer IData, TId, infer IConfig>\n ? IConfig['optional'] extends true\n ? IData | undefined\n : IData\n : never;\n };\n\n/** @internal */\nexport function createExtensionDataContainer<UData extends AnyExtensionDataRef>(\n values: Iterable<\n UData extends ExtensionDataRef<infer IData, infer IId>\n ? ExtensionDataValue<IData, IId>\n : never\n >,\n declaredRefs?: ExtensionDataRef<any, any, any>[],\n): ExtensionDataContainer<UData> {\n const container = new Map<string, ExtensionDataValue<any, any>>();\n const verifyRefs =\n declaredRefs && new Map(declaredRefs.map(ref => [ref.id, ref]));\n\n for (const output of values) {\n if (verifyRefs) {\n if (!verifyRefs.delete(output.id)) {\n throw new Error(\n `extension data '${output.id}' was provided but not declared`,\n );\n }\n }\n container.set(output.id, output);\n }\n\n const remainingRefs =\n verifyRefs &&\n Array.from(verifyRefs.values()).filter(ref => !ref.config.optional);\n if (remainingRefs && remainingRefs.length > 0) {\n throw new Error(\n `missing required extension data value(s) '${remainingRefs\n .map(ref => ref.id)\n .join(', ')}'`,\n );\n }\n\n return {\n get(ref) {\n return container.get(ref.id)?.value;\n },\n [Symbol.iterator]() {\n return container.values();\n },\n } as ExtensionDataContainer<UData>;\n}\n"],"names":[],"mappings":"AA6CgB,SAAA,4BAAA,CACd,QAKA,YAC+B,EAAA;AAC/B,EAAM,MAAA,SAAA,uBAAgB,GAA0C,EAAA;AAChE,EAAA,MAAM,UACJ,GAAA,YAAA,IAAgB,IAAI,GAAA,CAAI,YAAa,CAAA,GAAA,CAAI,CAAO,GAAA,KAAA,CAAC,GAAI,CAAA,EAAA,EAAI,GAAG,CAAC,CAAC,CAAA;AAEhE,EAAA,KAAA,MAAW,UAAU,MAAQ,EAAA;AAC3B,IAAA,IAAI,UAAY,EAAA;AACd,MAAA,IAAI,CAAC,UAAA,CAAW,MAAO,CAAA,MAAA,CAAO,EAAE,CAAG,EAAA;AACjC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,gBAAA,EAAmB,OAAO,EAAE,CAAA,+BAAA;AAAA,SAC9B;AAAA;AACF;AAEF,IAAU,SAAA,CAAA,GAAA,CAAI,MAAO,CAAA,EAAA,EAAI,MAAM,CAAA;AAAA;AAGjC,EAAA,MAAM,aACJ,GAAA,UAAA,IACA,KAAM,CAAA,IAAA,CAAK,UAAW,CAAA,MAAA,EAAQ,CAAA,CAAE,MAAO,CAAA,CAAA,GAAA,KAAO,CAAC,GAAA,CAAI,OAAO,QAAQ,CAAA;AACpE,EAAI,IAAA,aAAA,IAAiB,aAAc,CAAA,MAAA,GAAS,CAAG,EAAA;AAC7C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,0CAAA,EAA6C,cAC1C,GAAI,CAAA,CAAA,GAAA,KAAO,IAAI,EAAE,CAAA,CACjB,IAAK,CAAA,IAAI,CAAC,CAAA,CAAA;AAAA,KACf;AAAA;AAGF,EAAO,OAAA;AAAA,IACL,IAAI,GAAK,EAAA;AACP,MAAA,OAAO,SAAU,CAAA,GAAA,CAAI,GAAI,CAAA,EAAE,CAAG,EAAA,KAAA;AAAA,KAChC;AAAA,IACA,CAAC,MAAO,CAAA,QAAQ,CAAI,GAAA;AAClB,MAAA,OAAO,UAAU,MAAO,EAAA;AAAA;AAC1B,GACF;AACF;;;;"}