@backstage/plugin-app 0.2.0-next.1 → 0.2.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 +28 -0
- package/README.md +1 -7
- package/dist/apis/DefaultDialogApi.esm.js.map +1 -1
- package/dist/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.esm.js +40 -0
- package/dist/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.esm.js.map +1 -0
- package/dist/extensions/AppRoutes.esm.js +1 -4
- package/dist/extensions/AppRoutes.esm.js.map +1 -1
- package/dist/extensions/DialogDisplay.esm.js.map +1 -1
- package/dist/extensions/LegacyComponentsApi.esm.js +26 -0
- package/dist/extensions/LegacyComponentsApi.esm.js.map +1 -0
- package/dist/extensions/SwappableComponentsApi.esm.js +40 -0
- package/dist/extensions/SwappableComponentsApi.esm.js.map +1 -0
- package/dist/extensions/components.esm.js +21 -43
- package/dist/extensions/components.esm.js.map +1 -1
- package/dist/index.d.ts +86 -11
- package/dist/packages/frontend-internal/src/wiring/InternalExtensionDefinition.esm.js +7 -0
- package/dist/packages/frontend-internal/src/wiring/InternalExtensionDefinition.esm.js.map +1 -0
- package/dist/packages/frontend-internal/src/wiring/InternalFrontendPlugin.esm.js +7 -0
- package/dist/packages/frontend-internal/src/wiring/InternalFrontendPlugin.esm.js.map +1 -0
- package/dist/packages/frontend-internal/src/wiring/InternalSwappableComponentRef.esm.js +9 -0
- package/dist/packages/frontend-internal/src/wiring/InternalSwappableComponentRef.esm.js.map +1 -0
- package/dist/packages/opaque-internal/src/OpaqueType.esm.js +103 -0
- package/dist/packages/opaque-internal/src/OpaqueType.esm.js.map +1 -0
- package/dist/plugin.esm.js +9 -7
- package/dist/plugin.esm.js.map +1 -1
- package/dist/plugins/app/package.json.esm.js +7 -5
- package/dist/plugins/app/package.json.esm.js.map +1 -1
- package/package.json +10 -8
- package/dist/extensions/ComponentsApi.esm.js +0 -28
- package/dist/extensions/ComponentsApi.esm.js.map +0 -1
- package/dist/packages/app-defaults/src/defaults/components.esm.js +0 -46
- package/dist/packages/app-defaults/src/defaults/components.esm.js.map +0 -1
- package/dist/packages/frontend-app-api/src/apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js +0 -21
- package/dist/packages/frontend-app-api/src/apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @backstage/plugin-app
|
|
2
2
|
|
|
3
|
+
## 0.2.0-next.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- fda1bbc: **BREAKING**: The `componentsApi` implementation has been removed from the plugin and replaced with the new `SwappableComponentsApi` instead.
|
|
8
|
+
|
|
9
|
+
If you were overriding the `componentsApi` implementation, you can now use the new `SwappableComponentsApi` instead.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
// old
|
|
13
|
+
appPlugin.getExtension('api:app/components').override(...)
|
|
14
|
+
|
|
15
|
+
// new
|
|
16
|
+
appPlugin.getExtension('api:app/swappable-components').override(...)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- 91cbdf4: Log a warning when `SwappableComponent` extensions are installed outside of using the `app` plugin
|
|
22
|
+
- fda1bbc: Default implementations of core components are now provided by this package.
|
|
23
|
+
|
|
24
|
+
A backwards compatible `componentsApi` implementation is also provided from this package which uses the `SwappableComponentsApi` as the implementation. This backwards compatible wrapper will be removed in the future.
|
|
25
|
+
|
|
26
|
+
- 9831f4e: Adjusted the dialog API types to have more sensible defaults
|
|
27
|
+
- Updated dependencies
|
|
28
|
+
- @backstage/frontend-plugin-api@0.11.0-next.2
|
|
29
|
+
- @backstage/core-components@0.17.5-next.2
|
|
30
|
+
|
|
3
31
|
## 0.2.0-next.1
|
|
4
32
|
|
|
5
33
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
1
|
# app
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
_This plugin was created through the Backstage CLI_
|
|
6
|
-
|
|
7
|
-
## Getting started
|
|
8
|
-
|
|
9
|
-
Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/app](http://localhost:3000/app).
|
|
3
|
+
This plugin is part of the new frontend system, and represents the foundation of the frontend application itself, which then other features attach themselves into.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultDialogApi.esm.js","sources":["../../src/apis/DefaultDialogApi.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 { DialogApi, DialogApiDialog } from '@backstage/frontend-plugin-api';\n\nexport type OnShowDialog = (options: {\n component: (props: { dialog: DialogApiDialog<any> }) => React.JSX.Element;\n modal: boolean;\n}) => DialogApiDialog
|
|
1
|
+
{"version":3,"file":"DefaultDialogApi.esm.js","sources":["../../src/apis/DefaultDialogApi.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 { DialogApi, DialogApiDialog } from '@backstage/frontend-plugin-api';\n\nexport type OnShowDialog = (options: {\n component: (props: { dialog: DialogApiDialog<any> }) => React.JSX.Element;\n modal: boolean;\n}) => DialogApiDialog<unknown>;\n\n/**\n * Default implementation for the {@link DialogApi}.\n * @internal\n */\nexport class DefaultDialogApi implements DialogApi {\n #onShow?: OnShowDialog;\n\n show<TResult = void>(\n elementOrComponent:\n | JSX.Element\n | ((props: {\n dialog: DialogApiDialog<TResult | undefined>;\n }) => JSX.Element),\n ): DialogApiDialog<TResult | undefined> {\n if (!this.#onShow) {\n throw new Error('Dialog API has not been connected');\n }\n return this.#onShow({\n component:\n typeof elementOrComponent === 'function'\n ? elementOrComponent\n : () => elementOrComponent,\n modal: false,\n }) as DialogApiDialog<TResult | undefined>;\n }\n\n showModal<TResult = void>(\n elementOrComponent:\n | JSX.Element\n | ((props: { dialog: DialogApiDialog<TResult> }) => JSX.Element),\n ): DialogApiDialog<TResult> {\n if (!this.#onShow) {\n throw new Error('Dialog API has not been connected');\n }\n return this.#onShow({\n component:\n typeof elementOrComponent === 'function'\n ? elementOrComponent\n : () => elementOrComponent,\n modal: true,\n }) as DialogApiDialog<TResult>;\n }\n\n connect(onShow: OnShowDialog): void {\n this.#onShow = onShow;\n }\n}\n"],"names":[],"mappings":"AA2BO,MAAM,gBAAsC,CAAA;AAAA,EACjD,OAAA;AAAA,EAEA,KACE,kBAKsC,EAAA;AACtC,IAAI,IAAA,CAAC,KAAK,OAAS,EAAA;AACjB,MAAM,MAAA,IAAI,MAAM,mCAAmC,CAAA;AAAA;AAErD,IAAA,OAAO,KAAK,OAAQ,CAAA;AAAA,MAClB,SACE,EAAA,OAAO,kBAAuB,KAAA,UAAA,GAC1B,qBACA,MAAM,kBAAA;AAAA,MACZ,KAAO,EAAA;AAAA,KACR,CAAA;AAAA;AACH,EAEA,UACE,kBAG0B,EAAA;AAC1B,IAAI,IAAA,CAAC,KAAK,OAAS,EAAA;AACjB,MAAM,MAAA,IAAI,MAAM,mCAAmC,CAAA;AAAA;AAErD,IAAA,OAAO,KAAK,OAAQ,CAAA;AAAA,MAClB,SACE,EAAA,OAAO,kBAAuB,KAAA,UAAA,GAC1B,qBACA,MAAM,kBAAA;AAAA,MACZ,KAAO,EAAA;AAAA,KACR,CAAA;AAAA;AACH,EAEA,QAAQ,MAA4B,EAAA;AAClC,IAAA,IAAA,CAAK,OAAU,GAAA,MAAA;AAAA;AAEnB;;;;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { lazy } from 'react';
|
|
3
|
+
import { OpaqueSwappableComponentRef } from '../../packages/frontend-internal/src/wiring/InternalSwappableComponentRef.esm.js';
|
|
4
|
+
import '../../packages/frontend-internal/src/wiring/InternalExtensionDefinition.esm.js';
|
|
5
|
+
import '../../packages/frontend-internal/src/wiring/InternalFrontendPlugin.esm.js';
|
|
6
|
+
|
|
7
|
+
class DefaultSwappableComponentsApi {
|
|
8
|
+
#components;
|
|
9
|
+
static fromComponents(components) {
|
|
10
|
+
return new DefaultSwappableComponentsApi(
|
|
11
|
+
new Map(
|
|
12
|
+
components.map((entry) => {
|
|
13
|
+
return [
|
|
14
|
+
entry.ref.id,
|
|
15
|
+
entry.loader ? lazy(async () => ({
|
|
16
|
+
default: await entry.loader()
|
|
17
|
+
})) : void 0
|
|
18
|
+
];
|
|
19
|
+
})
|
|
20
|
+
)
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
constructor(components) {
|
|
24
|
+
this.#components = components;
|
|
25
|
+
}
|
|
26
|
+
getComponent(ref) {
|
|
27
|
+
const OverrideComponent = this.#components.get(ref.id);
|
|
28
|
+
const { defaultComponent: DefaultComponent, transformProps } = OpaqueSwappableComponentRef.toInternal(ref);
|
|
29
|
+
return (props) => {
|
|
30
|
+
const innerProps = transformProps?.(props) ?? props;
|
|
31
|
+
if (OverrideComponent) {
|
|
32
|
+
return /* @__PURE__ */ jsx(OverrideComponent, { ...innerProps });
|
|
33
|
+
}
|
|
34
|
+
return /* @__PURE__ */ jsx(DefaultComponent, { ...innerProps });
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { DefaultSwappableComponentsApi };
|
|
40
|
+
//# sourceMappingURL=DefaultSwappableComponentsApi.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DefaultSwappableComponentsApi.esm.js","sources":["../../../src/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n SwappableComponentRef,\n SwappableComponentsApi,\n SwappableComponentBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport { OpaqueSwappableComponentRef } from '@internal/frontend';\n\nimport { lazy } from 'react';\n\n/**\n * Implementation for the {@link SwappableComponentsApi}\n *\n * @internal\n */\nexport class DefaultSwappableComponentsApi implements SwappableComponentsApi {\n #components: Map<string, ((props: object) => JSX.Element | null) | undefined>;\n\n static fromComponents(\n components: Array<typeof SwappableComponentBlueprint.dataRefs.component.T>,\n ) {\n return new DefaultSwappableComponentsApi(\n new Map(\n components.map(entry => {\n return [\n entry.ref.id,\n entry.loader\n ? lazy(async () => ({\n default: await entry.loader!(),\n }))\n : undefined,\n ];\n }),\n ),\n );\n }\n\n constructor(components: Map<string, any>) {\n this.#components = components;\n }\n\n getComponent(\n ref: SwappableComponentRef<any>,\n ): (props: object) => JSX.Element | null {\n const OverrideComponent = this.#components.get(ref.id);\n const { defaultComponent: DefaultComponent, transformProps } =\n OpaqueSwappableComponentRef.toInternal(ref);\n\n return (props: object) => {\n const innerProps = transformProps?.(props) ?? props;\n\n if (OverrideComponent) {\n return <OverrideComponent {...innerProps} />;\n }\n\n return <DefaultComponent {...innerProps} />;\n };\n }\n}\n"],"names":[],"mappings":";;;;;;AA8BO,MAAM,6BAAgE,CAAA;AAAA,EAC3E,WAAA;AAAA,EAEA,OAAO,eACL,UACA,EAAA;AACA,IAAA,OAAO,IAAI,6BAAA;AAAA,MACT,IAAI,GAAA;AAAA,QACF,UAAA,CAAW,IAAI,CAAS,KAAA,KAAA;AACtB,UAAO,OAAA;AAAA,YACL,MAAM,GAAI,CAAA,EAAA;AAAA,YACV,KAAA,CAAM,MACF,GAAA,IAAA,CAAK,aAAa;AAAA,cAChB,OAAA,EAAS,MAAM,KAAA,CAAM,MAAQ;AAAA,cAC7B,CACF,GAAA,KAAA;AAAA,WACN;AAAA,SACD;AAAA;AACH,KACF;AAAA;AACF,EAEA,YAAY,UAA8B,EAAA;AACxC,IAAA,IAAA,CAAK,WAAc,GAAA,UAAA;AAAA;AACrB,EAEA,aACE,GACuC,EAAA;AACvC,IAAA,MAAM,iBAAoB,GAAA,IAAA,CAAK,WAAY,CAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AACrD,IAAA,MAAM,EAAE,gBAAkB,EAAA,gBAAA,EAAkB,gBAC1C,GAAA,2BAAA,CAA4B,WAAW,GAAG,CAAA;AAE5C,IAAA,OAAO,CAAC,KAAkB,KAAA;AACxB,MAAM,MAAA,UAAA,GAAa,cAAiB,GAAA,KAAK,CAAK,IAAA,KAAA;AAE9C,MAAA,IAAI,iBAAmB,EAAA;AACrB,QAAO,uBAAA,GAAA,CAAC,iBAAmB,EAAA,EAAA,GAAG,UAAY,EAAA,CAAA;AAAA;AAG5C,MAAO,uBAAA,GAAA,CAAC,gBAAkB,EAAA,EAAA,GAAG,UAAY,EAAA,CAAA;AAAA,KAC3C;AAAA;AAEJ;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { createExtension, createExtensionInput, coreExtensionData,
|
|
2
|
+
import { createExtension, createExtensionInput, coreExtensionData, NotFoundErrorPage } from '@backstage/frontend-plugin-api';
|
|
3
3
|
import { useRoutes } from 'react-router-dom';
|
|
4
4
|
|
|
5
5
|
const AppRoutes = createExtension({
|
|
@@ -15,9 +15,6 @@ const AppRoutes = createExtension({
|
|
|
15
15
|
output: [coreExtensionData.reactElement],
|
|
16
16
|
factory({ inputs }) {
|
|
17
17
|
const Routes = () => {
|
|
18
|
-
const NotFoundErrorPage = useComponentRef(
|
|
19
|
-
coreComponentRefs.notFoundErrorPage
|
|
20
|
-
);
|
|
21
18
|
const element = useRoutes([
|
|
22
19
|
...inputs.routes.map((route) => ({
|
|
23
20
|
path: `${route.get(coreExtensionData.routePath).replace(/\/$/, "")}/*`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppRoutes.esm.js","sources":["../../src/extensions/AppRoutes.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createExtension,\n coreExtensionData,\n createExtensionInput,\n
|
|
1
|
+
{"version":3,"file":"AppRoutes.esm.js","sources":["../../src/extensions/AppRoutes.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createExtension,\n coreExtensionData,\n createExtensionInput,\n NotFoundErrorPage,\n} from '@backstage/frontend-plugin-api';\nimport { useRoutes } from 'react-router-dom';\n\nexport const AppRoutes = createExtension({\n name: 'routes',\n attachTo: { id: 'app/layout', input: 'content' },\n inputs: {\n routes: createExtensionInput([\n coreExtensionData.routePath,\n coreExtensionData.routeRef.optional(),\n coreExtensionData.reactElement,\n ]),\n },\n output: [coreExtensionData.reactElement],\n factory({ inputs }) {\n const Routes = () => {\n const element = useRoutes([\n ...inputs.routes.map(route => ({\n path: `${route\n .get(coreExtensionData.routePath)\n .replace(/\\/$/, '')}/*`,\n element: route.get(coreExtensionData.reactElement),\n })),\n {\n path: '*',\n element: <NotFoundErrorPage />,\n },\n ]);\n\n return element;\n };\n\n return [coreExtensionData.reactElement(<Routes />)];\n },\n});\n"],"names":[],"mappings":";;;;AAwBO,MAAM,YAAY,eAAgB,CAAA;AAAA,EACvC,IAAM,EAAA,QAAA;AAAA,EACN,QAAU,EAAA,EAAE,EAAI,EAAA,YAAA,EAAc,OAAO,SAAU,EAAA;AAAA,EAC/C,MAAQ,EAAA;AAAA,IACN,QAAQ,oBAAqB,CAAA;AAAA,MAC3B,iBAAkB,CAAA,SAAA;AAAA,MAClB,iBAAA,CAAkB,SAAS,QAAS,EAAA;AAAA,MACpC,iBAAkB,CAAA;AAAA,KACnB;AAAA,GACH;AAAA,EACA,MAAA,EAAQ,CAAC,iBAAA,CAAkB,YAAY,CAAA;AAAA,EACvC,OAAA,CAAQ,EAAE,MAAA,EAAU,EAAA;AAClB,IAAA,MAAM,SAAS,MAAM;AACnB,MAAA,MAAM,UAAU,SAAU,CAAA;AAAA,QACxB,GAAG,MAAA,CAAO,MAAO,CAAA,GAAA,CAAI,CAAU,KAAA,MAAA;AAAA,UAC7B,IAAA,EAAM,CAAG,EAAA,KAAA,CACN,GAAI,CAAA,iBAAA,CAAkB,SAAS,CAC/B,CAAA,OAAA,CAAQ,KAAO,EAAA,EAAE,CAAC,CAAA,EAAA,CAAA;AAAA,UACrB,OAAS,EAAA,KAAA,CAAM,GAAI,CAAA,iBAAA,CAAkB,YAAY;AAAA,SACjD,CAAA,CAAA;AAAA,QACF;AAAA,UACE,IAAM,EAAA,GAAA;AAAA,UACN,OAAA,sBAAU,iBAAkB,EAAA,EAAA;AAAA;AAC9B,OACD,CAAA;AAED,MAAO,OAAA,OAAA;AAAA,KACT;AAEA,IAAA,OAAO,CAAC,iBAAkB,CAAA,YAAA,iBAAc,GAAA,CAAA,MAAA,EAAA,EAAO,CAAE,CAAC,CAAA;AAAA;AAEtD,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DialogDisplay.esm.js","sources":["../../src/extensions/DialogDisplay.tsx"],"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 { Fragment, useEffect, useState } from 'react';\nimport {\n AppRootElementBlueprint,\n DialogApi,\n DialogApiDialog,\n dialogApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { createDeferred } from '@backstage/types';\nimport { OnShowDialog } from '../apis/DefaultDialogApi';\nimport Dialog from '@material-ui/core/Dialog';\n\nlet dialogId = 0;\nfunction getDialogId() {\n dialogId += 1;\n return dialogId.toString(36);\n}\n\ntype DialogState = DialogApiDialog & {\n id: string;\n modal: boolean;\n};\n\n/**\n * The other half of the default implementation of the {@link DialogApi}.\n *\n * This component is responsible for rendering the dialogs in the React tree and managing a stack of dialogs.\n * It expects the implementation of the {@link DialogApi} to be the `DefaultDialogApi`. If one is replaced the other must be too.\n * @internal\n */\nfunction DialogDisplay({\n dialogApi,\n}: {\n dialogApi: DialogApi & { connect(onShow: OnShowDialog): void };\n}) {\n const [dialogs, setDialogs] = useState<\n { dialog: DialogState; element: React.JSX.Element }[]\n >([]);\n\n useEffect(() => {\n dialogApi.connect(options => {\n const id = getDialogId();\n const deferred = createDeferred<unknown>();\n const dialog: DialogState = {\n id,\n modal: options.modal,\n close(result) {\n deferred.resolve(result);\n setDialogs(ds => ds.filter(d => d.dialog.id !== id));\n },\n update(ElementOrComponent) {\n const element =\n typeof ElementOrComponent === 'function' ? (\n <ElementOrComponent dialog={dialog} />\n ) : (\n ElementOrComponent\n );\n setDialogs(ds =>\n ds.map(d => (d.dialog.id === id ? { dialog, element } : d)),\n );\n },\n async result() {\n return deferred;\n },\n };\n const element = <options.component dialog={dialog} />;\n setDialogs(ds => [...ds, { dialog, element }]);\n return dialog;\n });\n }, [dialogApi]);\n\n if (dialogs.length > 0) {\n const lastDialog = dialogs[dialogs.length - 1];\n return (\n <Dialog\n open\n onClose={() => {\n if (!lastDialog.dialog.modal) {\n lastDialog.dialog.close();\n }\n }}\n >\n {lastDialog.element}\n </Dialog>\n );\n }\n\n return null;\n}\n\nexport const dialogDisplayAppRootElement =\n AppRootElementBlueprint.makeWithOverrides({\n name: 'dialog-display',\n factory(originalFactory, { apis }) {\n const dialogApi = apis.get(dialogApiRef);\n if (!isInternalDialogApi(dialogApi)) {\n return originalFactory({\n element: <Fragment />,\n });\n }\n return originalFactory({\n element: <DialogDisplay dialogApi={dialogApi} />,\n });\n },\n });\n\nfunction isInternalDialogApi(\n dialogApi?: DialogApi,\n): dialogApi is DialogApi & { connect(onShow: OnShowDialog): void } {\n if (!dialogApi) {\n return false;\n }\n return 'connect' in dialogApi;\n}\n"],"names":["element"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DialogDisplay.esm.js","sources":["../../src/extensions/DialogDisplay.tsx"],"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 { Fragment, useEffect, useState } from 'react';\nimport {\n AppRootElementBlueprint,\n DialogApi,\n DialogApiDialog,\n dialogApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { createDeferred } from '@backstage/types';\nimport { OnShowDialog } from '../apis/DefaultDialogApi';\nimport Dialog from '@material-ui/core/Dialog';\n\nlet dialogId = 0;\nfunction getDialogId() {\n dialogId += 1;\n return dialogId.toString(36);\n}\n\ntype DialogState = DialogApiDialog<unknown> & {\n id: string;\n modal: boolean;\n};\n\n/**\n * The other half of the default implementation of the {@link DialogApi}.\n *\n * This component is responsible for rendering the dialogs in the React tree and managing a stack of dialogs.\n * It expects the implementation of the {@link DialogApi} to be the `DefaultDialogApi`. If one is replaced the other must be too.\n * @internal\n */\nfunction DialogDisplay({\n dialogApi,\n}: {\n dialogApi: DialogApi & { connect(onShow: OnShowDialog): void };\n}) {\n const [dialogs, setDialogs] = useState<\n { dialog: DialogState; element: React.JSX.Element }[]\n >([]);\n\n useEffect(() => {\n dialogApi.connect(options => {\n const id = getDialogId();\n const deferred = createDeferred<unknown>();\n const dialog: DialogState = {\n id,\n modal: options.modal,\n close(result) {\n deferred.resolve(result);\n setDialogs(ds => ds.filter(d => d.dialog.id !== id));\n },\n update(ElementOrComponent) {\n const element =\n typeof ElementOrComponent === 'function' ? (\n <ElementOrComponent dialog={dialog} />\n ) : (\n ElementOrComponent\n );\n setDialogs(ds =>\n ds.map(d => (d.dialog.id === id ? { dialog, element } : d)),\n );\n },\n async result() {\n return deferred;\n },\n };\n const element = <options.component dialog={dialog} />;\n setDialogs(ds => [...ds, { dialog, element }]);\n return dialog;\n });\n }, [dialogApi]);\n\n if (dialogs.length > 0) {\n const lastDialog = dialogs[dialogs.length - 1];\n return (\n <Dialog\n open\n onClose={() => {\n if (!lastDialog.dialog.modal) {\n lastDialog.dialog.close();\n }\n }}\n >\n {lastDialog.element}\n </Dialog>\n );\n }\n\n return null;\n}\n\nexport const dialogDisplayAppRootElement =\n AppRootElementBlueprint.makeWithOverrides({\n name: 'dialog-display',\n factory(originalFactory, { apis }) {\n const dialogApi = apis.get(dialogApiRef);\n if (!isInternalDialogApi(dialogApi)) {\n return originalFactory({\n element: <Fragment />,\n });\n }\n return originalFactory({\n element: <DialogDisplay dialogApi={dialogApi} />,\n });\n },\n });\n\nfunction isInternalDialogApi(\n dialogApi?: DialogApi,\n): dialogApi is DialogApi & { connect(onShow: OnShowDialog): void } {\n if (!dialogApi) {\n return false;\n }\n return 'connect' in dialogApi;\n}\n"],"names":["element"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ApiBlueprint, createApiRef, Progress, NotFoundErrorPage, ErrorDisplay } from '@backstage/frontend-plugin-api';
|
|
2
|
+
|
|
3
|
+
const LegacyComponentsApi = ApiBlueprint.make({
|
|
4
|
+
name: "components",
|
|
5
|
+
params: (defineParams) => defineParams({
|
|
6
|
+
api: createApiRef({ id: "core.components" }),
|
|
7
|
+
deps: {},
|
|
8
|
+
factory: () => ({
|
|
9
|
+
getComponent(ref) {
|
|
10
|
+
if (ref.id === "core.components.progress") {
|
|
11
|
+
return Progress;
|
|
12
|
+
}
|
|
13
|
+
if (ref.id === "core.components.notFoundErrorPage") {
|
|
14
|
+
return NotFoundErrorPage;
|
|
15
|
+
}
|
|
16
|
+
if (ref.id === "core.components.errorBoundaryFallback") {
|
|
17
|
+
return ErrorDisplay;
|
|
18
|
+
}
|
|
19
|
+
throw new Error(`No implementation found for component ref ${ref}`);
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export { LegacyComponentsApi };
|
|
26
|
+
//# sourceMappingURL=LegacyComponentsApi.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LegacyComponentsApi.esm.js","sources":["../../src/extensions/LegacyComponentsApi.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 ApiBlueprint,\n createApiRef,\n ErrorDisplay,\n NotFoundErrorPage,\n Progress,\n} from '@backstage/frontend-plugin-api';\nimport { ComponentType } from 'react';\n\n/**\n * This is the old component API that has been replaced by the new SwappableComponentsApi.\n *\n * This backwards compatibility implementation exists to avoid breaking older plugins.\n *\n * This was added for the 1.42 release, and can be removed in the future.\n *\n * @internal\n */\nexport const LegacyComponentsApi = ApiBlueprint.make({\n name: 'components',\n params: defineParams =>\n defineParams({\n api: createApiRef<{\n getComponent(ref: { id: string }): ComponentType<any>;\n }>({ id: 'core.components' }),\n deps: {},\n factory: () => ({\n getComponent(ref) {\n if (ref.id === 'core.components.progress') {\n return Progress;\n }\n if (ref.id === 'core.components.notFoundErrorPage') {\n return NotFoundErrorPage;\n }\n if (ref.id === 'core.components.errorBoundaryFallback') {\n return ErrorDisplay;\n }\n throw new Error(`No implementation found for component ref ${ref}`);\n },\n }),\n }),\n});\n"],"names":[],"mappings":";;AAkCa,MAAA,mBAAA,GAAsB,aAAa,IAAK,CAAA;AAAA,EACnD,IAAM,EAAA,YAAA;AAAA,EACN,MAAA,EAAQ,kBACN,YAAa,CAAA;AAAA,IACX,GAAK,EAAA,YAAA,CAEF,EAAE,EAAA,EAAI,mBAAmB,CAAA;AAAA,IAC5B,MAAM,EAAC;AAAA,IACP,SAAS,OAAO;AAAA,MACd,aAAa,GAAK,EAAA;AAChB,QAAI,IAAA,GAAA,CAAI,OAAO,0BAA4B,EAAA;AACzC,UAAO,OAAA,QAAA;AAAA;AAET,QAAI,IAAA,GAAA,CAAI,OAAO,mCAAqC,EAAA;AAClD,UAAO,OAAA,iBAAA;AAAA;AAET,QAAI,IAAA,GAAA,CAAI,OAAO,uCAAyC,EAAA;AACtD,UAAO,OAAA,YAAA;AAAA;AAET,QAAA,MAAM,IAAI,KAAA,CAAM,CAA6C,0CAAA,EAAA,GAAG,CAAE,CAAA,CAAA;AAAA;AACpE,KACF;AAAA,GACD;AACL,CAAC;;;;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ApiBlueprint, createExtensionInput, SwappableComponentBlueprint, swappableComponentsApiRef } from '@backstage/frontend-plugin-api';
|
|
2
|
+
import { DefaultSwappableComponentsApi } from '../apis/SwappableComponentsApi/DefaultSwappableComponentsApi.esm.js';
|
|
3
|
+
|
|
4
|
+
const SwappableComponentsApi = ApiBlueprint.makeWithOverrides({
|
|
5
|
+
name: "swappable-components",
|
|
6
|
+
inputs: {
|
|
7
|
+
components: createExtensionInput([
|
|
8
|
+
SwappableComponentBlueprint.dataRefs.component
|
|
9
|
+
])
|
|
10
|
+
},
|
|
11
|
+
factory: (originalFactory, { inputs }) => {
|
|
12
|
+
return originalFactory(
|
|
13
|
+
(defineParams) => defineParams({
|
|
14
|
+
api: swappableComponentsApiRef,
|
|
15
|
+
deps: {},
|
|
16
|
+
factory: () => {
|
|
17
|
+
const nonAppExtensions = inputs.components.filter(
|
|
18
|
+
(i) => i.node.spec.plugin?.id !== "app"
|
|
19
|
+
);
|
|
20
|
+
if (nonAppExtensions.length > 0) {
|
|
21
|
+
console.warn(
|
|
22
|
+
`SwappableComponents should only be installed as an extension in the app plugin. You can either use appPlugin.override(), or provide a module for the app-plugin with the extension there instead. Invalid extensions: ${nonAppExtensions.map((i) => i.node.spec.id).join(", ")}`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
const appExtensions = inputs.components.filter(
|
|
26
|
+
(i) => i.node.spec.plugin?.id === "app"
|
|
27
|
+
);
|
|
28
|
+
return DefaultSwappableComponentsApi.fromComponents(
|
|
29
|
+
appExtensions.map(
|
|
30
|
+
(i) => i.get(SwappableComponentBlueprint.dataRefs.component)
|
|
31
|
+
)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export { SwappableComponentsApi };
|
|
40
|
+
//# sourceMappingURL=SwappableComponentsApi.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwappableComponentsApi.esm.js","sources":["../../src/extensions/SwappableComponentsApi.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 SwappableComponentBlueprint,\n createExtensionInput,\n ApiBlueprint,\n swappableComponentsApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { DefaultSwappableComponentsApi } from '../apis/SwappableComponentsApi';\n\n/**\n * Contains the shareable components installed into the app.\n */\nexport const SwappableComponentsApi = ApiBlueprint.makeWithOverrides({\n name: 'swappable-components',\n inputs: {\n components: createExtensionInput([\n SwappableComponentBlueprint.dataRefs.component,\n ]),\n },\n factory: (originalFactory, { inputs }) => {\n return originalFactory(defineParams =>\n defineParams({\n api: swappableComponentsApiRef,\n deps: {},\n factory: () => {\n const nonAppExtensions = inputs.components.filter(\n i => i.node.spec.plugin?.id !== 'app',\n );\n\n if (nonAppExtensions.length > 0) {\n // eslint-disable-next-line no-console\n console.warn(\n `SwappableComponents should only be installed as an extension in the app plugin. You can either use appPlugin.override(), or provide a module for the app-plugin with the extension there instead. Invalid extensions: ${nonAppExtensions\n .map(i => i.node.spec.id)\n .join(', ')}`,\n );\n }\n\n const appExtensions = inputs.components.filter(\n i => i.node.spec.plugin?.id === 'app',\n );\n\n return DefaultSwappableComponentsApi.fromComponents(\n appExtensions.map(i =>\n i.get(SwappableComponentBlueprint.dataRefs.component),\n ),\n );\n },\n }),\n );\n },\n});\n"],"names":[],"mappings":";;;AA2Ba,MAAA,sBAAA,GAAyB,aAAa,iBAAkB,CAAA;AAAA,EACnE,IAAM,EAAA,sBAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,YAAY,oBAAqB,CAAA;AAAA,MAC/B,4BAA4B,QAAS,CAAA;AAAA,KACtC;AAAA,GACH;AAAA,EACA,OAAS,EAAA,CAAC,eAAiB,EAAA,EAAE,QAAa,KAAA;AACxC,IAAO,OAAA,eAAA;AAAA,MAAgB,kBACrB,YAAa,CAAA;AAAA,QACX,GAAK,EAAA,yBAAA;AAAA,QACL,MAAM,EAAC;AAAA,QACP,SAAS,MAAM;AACb,UAAM,MAAA,gBAAA,GAAmB,OAAO,UAAW,CAAA,MAAA;AAAA,YACzC,CAAK,CAAA,KAAA,CAAA,CAAE,IAAK,CAAA,IAAA,CAAK,QAAQ,EAAO,KAAA;AAAA,WAClC;AAEA,UAAI,IAAA,gBAAA,CAAiB,SAAS,CAAG,EAAA;AAE/B,YAAQ,OAAA,CAAA,IAAA;AAAA,cACN,CAAA,sNAAA,EAAyN,gBACtN,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA,CAAA,CAAE,IAAK,CAAA,IAAA,CAAK,EAAE,CAAA,CACvB,IAAK,CAAA,IAAI,CAAC,CAAA;AAAA,aACf;AAAA;AAGF,UAAM,MAAA,aAAA,GAAgB,OAAO,UAAW,CAAA,MAAA;AAAA,YACtC,CAAK,CAAA,KAAA,CAAA,CAAE,IAAK,CAAA,IAAA,CAAK,QAAQ,EAAO,KAAA;AAAA,WAClC;AAEA,UAAA,OAAO,6BAA8B,CAAA,cAAA;AAAA,YACnC,aAAc,CAAA,GAAA;AAAA,cAAI,CAChB,CAAA,KAAA,CAAA,CAAE,GAAI,CAAA,2BAAA,CAA4B,SAAS,SAAS;AAAA;AACtD,WACF;AAAA;AACF,OACD;AAAA,KACH;AAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1,55 +1,33 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { SwappableComponentBlueprint, Progress as Progress$1, NotFoundErrorPage as NotFoundErrorPage$1, ErrorDisplay as ErrorDisplay$1 } from '@backstage/frontend-plugin-api';
|
|
3
|
+
import { Progress as Progress$2, ErrorPage, ErrorPanel } from '@backstage/core-components';
|
|
2
4
|
import Button from '@material-ui/core/Button';
|
|
3
|
-
import { createComponentExtension, coreComponentRefs } from '@backstage/frontend-plugin-api';
|
|
4
|
-
import { ErrorPanel } from '@backstage/core-components';
|
|
5
|
-
import '../packages/app-defaults/src/defaults/apis.esm.js';
|
|
6
|
-
import { components } from '../packages/app-defaults/src/defaults/components.esm.js';
|
|
7
|
-
import '@material-ui/icons/Apartment';
|
|
8
|
-
import '@material-ui/icons/BrokenImage';
|
|
9
|
-
import '@material-ui/icons/Category';
|
|
10
|
-
import '@material-ui/icons/CreateNewFolder';
|
|
11
|
-
import '@material-ui/icons/Subject';
|
|
12
|
-
import '@material-ui/icons/Search';
|
|
13
|
-
import '@material-ui/icons/Chat';
|
|
14
|
-
import '@material-ui/icons/Dashboard';
|
|
15
|
-
import '@material-ui/icons/Description';
|
|
16
|
-
import '@material-ui/icons/Email';
|
|
17
|
-
import '@material-ui/icons/Extension';
|
|
18
|
-
import '@material-ui/icons/GitHub';
|
|
19
|
-
import '@material-ui/icons/Help';
|
|
20
|
-
import '@material-ui/icons/LocationOn';
|
|
21
|
-
import '@material-ui/icons/Memory';
|
|
22
|
-
import '@material-ui/icons/MenuBook';
|
|
23
|
-
import '@material-ui/icons/People';
|
|
24
|
-
import '@material-ui/icons/Person';
|
|
25
|
-
import '@material-ui/icons/Warning';
|
|
26
|
-
import '@material-ui/icons/Storage';
|
|
27
|
-
import '@material-ui/icons/FeaturedPlayList';
|
|
28
|
-
import '@material-ui/icons/Star';
|
|
29
|
-
import '@material-ui/icons/StarBorder';
|
|
30
|
-
import '@material-ui/icons/OpenInNew';
|
|
31
|
-
import '@backstage/theme';
|
|
32
|
-
import '@material-ui/icons/Brightness2';
|
|
33
|
-
import '@material-ui/icons/WbSunny';
|
|
34
5
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
6
|
+
const Progress = SwappableComponentBlueprint.make({
|
|
7
|
+
name: "core-progress",
|
|
8
|
+
params: (define) => define({
|
|
9
|
+
component: Progress$1,
|
|
10
|
+
loader: () => Progress$2
|
|
11
|
+
})
|
|
38
12
|
});
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
13
|
+
const NotFoundErrorPage = SwappableComponentBlueprint.make({
|
|
14
|
+
name: "core-not-found-error-page",
|
|
15
|
+
params: (define) => define({
|
|
16
|
+
component: NotFoundErrorPage$1,
|
|
17
|
+
loader: () => () => /* @__PURE__ */ jsx(ErrorPage, { status: "404", statusMessage: "PAGE NOT FOUND" })
|
|
18
|
+
})
|
|
42
19
|
});
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
20
|
+
const ErrorDisplay = SwappableComponentBlueprint.make({
|
|
21
|
+
name: "core-error-display",
|
|
22
|
+
params: (define) => define({
|
|
23
|
+
component: ErrorDisplay$1,
|
|
24
|
+
loader: () => (props) => {
|
|
47
25
|
const { plugin, error, resetError } = props;
|
|
48
26
|
const title = `Error in ${plugin?.id}`;
|
|
49
27
|
return /* @__PURE__ */ jsx(ErrorPanel, { title, error, defaultExpanded: true, children: /* @__PURE__ */ jsx(Button, { variant: "outlined", onClick: resetError, children: "Retry" }) });
|
|
50
28
|
}
|
|
51
|
-
}
|
|
29
|
+
})
|
|
52
30
|
});
|
|
53
31
|
|
|
54
|
-
export {
|
|
32
|
+
export { ErrorDisplay, NotFoundErrorPage, Progress };
|
|
55
33
|
//# sourceMappingURL=components.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.esm.js","sources":["../../src/extensions/components.tsx"],"sourcesContent":["/*\n * Copyright
|
|
1
|
+
{"version":3,"file":"components.esm.js","sources":["../../src/extensions/components.tsx"],"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 */\nimport {\n NotFoundErrorPage as SwappableNotFoundErrorPage,\n Progress as SwappableProgress,\n ErrorDisplay as SwappableErrorDisplay,\n SwappableComponentBlueprint,\n} from '@backstage/frontend-plugin-api';\n\nimport {\n ErrorPage,\n ErrorPanel,\n Progress as ProgressComponent,\n} from '@backstage/core-components';\nimport Button from '@material-ui/core/Button';\n\nexport const Progress = SwappableComponentBlueprint.make({\n name: 'core-progress',\n params: define =>\n define({\n component: SwappableProgress,\n loader: () => ProgressComponent,\n }),\n});\n\nexport const NotFoundErrorPage = SwappableComponentBlueprint.make({\n name: 'core-not-found-error-page',\n params: define =>\n define({\n component: SwappableNotFoundErrorPage,\n loader: () => () =>\n <ErrorPage status=\"404\" statusMessage=\"PAGE NOT FOUND\" />,\n }),\n});\n\nexport const ErrorDisplay = SwappableComponentBlueprint.make({\n name: 'core-error-display',\n params: define =>\n define({\n component: SwappableErrorDisplay,\n loader: () => props => {\n const { plugin, error, resetError } = props;\n const title = `Error in ${plugin?.id}`;\n return (\n <ErrorPanel title={title} error={error} defaultExpanded>\n <Button variant=\"outlined\" onClick={resetError}>\n Retry\n </Button>\n </ErrorPanel>\n );\n },\n }),\n});\n"],"names":["SwappableProgress","ProgressComponent","SwappableNotFoundErrorPage","SwappableErrorDisplay"],"mappings":";;;;;AA6Ba,MAAA,QAAA,GAAW,4BAA4B,IAAK,CAAA;AAAA,EACvD,IAAM,EAAA,eAAA;AAAA,EACN,MAAA,EAAQ,YACN,MAAO,CAAA;AAAA,IACL,SAAW,EAAAA,UAAA;AAAA,IACX,QAAQ,MAAMC;AAAA,GACf;AACL,CAAC;AAEY,MAAA,iBAAA,GAAoB,4BAA4B,IAAK,CAAA;AAAA,EAChE,IAAM,EAAA,2BAAA;AAAA,EACN,MAAA,EAAQ,YACN,MAAO,CAAA;AAAA,IACL,SAAW,EAAAC,mBAAA;AAAA,IACX,MAAA,EAAQ,MAAM,sBACZ,GAAA,CAAC,aAAU,MAAO,EAAA,KAAA,EAAM,eAAc,gBAAiB,EAAA;AAAA,GAC1D;AACL,CAAC;AAEY,MAAA,YAAA,GAAe,4BAA4B,IAAK,CAAA;AAAA,EAC3D,IAAM,EAAA,oBAAA;AAAA,EACN,MAAA,EAAQ,YACN,MAAO,CAAA;AAAA,IACL,SAAW,EAAAC,cAAA;AAAA,IACX,MAAA,EAAQ,MAAM,CAAS,KAAA,KAAA;AACrB,MAAA,MAAM,EAAE,MAAA,EAAQ,KAAO,EAAA,UAAA,EAAe,GAAA,KAAA;AACtC,MAAM,MAAA,KAAA,GAAQ,CAAY,SAAA,EAAA,MAAA,EAAQ,EAAE,CAAA,CAAA;AACpC,MAAA,uBACG,GAAA,CAAA,UAAA,EAAA,EAAW,KAAc,EAAA,KAAA,EAAc,eAAe,EAAA,IAAA,EACrD,QAAC,kBAAA,GAAA,CAAA,MAAA,EAAA,EAAO,OAAQ,EAAA,UAAA,EAAW,OAAS,EAAA,UAAA,EAAY,mBAEhD,CACF,EAAA,CAAA;AAAA;AAEJ,GACD;AACL,CAAC;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -182,20 +182,12 @@ declare const appPlugin: _backstage_frontend_plugin_api.FrontendPlugin<{}, {}, {
|
|
|
182
182
|
params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
183
183
|
}>;
|
|
184
184
|
"api:app/components": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
185
|
+
kind: "api";
|
|
186
|
+
name: "components";
|
|
185
187
|
config: {};
|
|
186
188
|
configInput: {};
|
|
187
189
|
output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
188
|
-
inputs: {
|
|
189
|
-
components: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
|
|
190
|
-
ref: _backstage_frontend_plugin_api.ComponentRef;
|
|
191
|
-
impl: react.ComponentType;
|
|
192
|
-
}, "core.component.component", {}>, {
|
|
193
|
-
singleton: false;
|
|
194
|
-
optional: false;
|
|
195
|
-
}>;
|
|
196
|
-
};
|
|
197
|
-
kind: "api";
|
|
198
|
-
name: "components";
|
|
190
|
+
inputs: {};
|
|
199
191
|
params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
200
192
|
}>;
|
|
201
193
|
"api:app/dialog": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
@@ -358,6 +350,23 @@ declare const appPlugin: _backstage_frontend_plugin_api.FrontendPlugin<{}, {}, {
|
|
|
358
350
|
inputs: {};
|
|
359
351
|
params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
360
352
|
}>;
|
|
353
|
+
"api:app/swappable-components": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
354
|
+
config: {};
|
|
355
|
+
configInput: {};
|
|
356
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
357
|
+
inputs: {
|
|
358
|
+
components: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
|
|
359
|
+
ref: _backstage_frontend_plugin_api.SwappableComponentRef;
|
|
360
|
+
loader: (() => (props: {}) => JSX.Element | null) | (() => Promise<(props: {}) => JSX.Element | null>);
|
|
361
|
+
}, "core.swappableComponent", {}>, {
|
|
362
|
+
singleton: false;
|
|
363
|
+
optional: false;
|
|
364
|
+
}>;
|
|
365
|
+
};
|
|
366
|
+
kind: "api";
|
|
367
|
+
name: "swappable-components";
|
|
368
|
+
params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
369
|
+
}>;
|
|
361
370
|
"api:app/translations": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
362
371
|
config: {};
|
|
363
372
|
configInput: {};
|
|
@@ -438,6 +447,72 @@ declare const appPlugin: _backstage_frontend_plugin_api.FrontendPlugin<{}, {}, {
|
|
|
438
447
|
element: JSX.Element;
|
|
439
448
|
};
|
|
440
449
|
}>;
|
|
450
|
+
"component:app/core-error-display": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
451
|
+
kind: "component";
|
|
452
|
+
name: "core-error-display";
|
|
453
|
+
config: {};
|
|
454
|
+
configInput: {};
|
|
455
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<{
|
|
456
|
+
ref: _backstage_frontend_plugin_api.SwappableComponentRef;
|
|
457
|
+
loader: (() => (props: {}) => JSX.Element | null) | (() => Promise<(props: {}) => JSX.Element | null>);
|
|
458
|
+
}, "core.swappableComponent", {}>;
|
|
459
|
+
inputs: {};
|
|
460
|
+
params: <Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<any>>(params: {
|
|
461
|
+
component: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<any, infer IExternalComponentProps> ? {
|
|
462
|
+
ref: Ref;
|
|
463
|
+
} & ((props: IExternalComponentProps) => JSX.Element | null) : never;
|
|
464
|
+
loader: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<infer IInnerComponentProps, any> ? (() => (props: IInnerComponentProps) => JSX.Element | null) | (() => Promise<(props: IInnerComponentProps) => JSX.Element | null>) : never;
|
|
465
|
+
}) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<{
|
|
466
|
+
component: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<any, infer IExternalComponentProps> ? {
|
|
467
|
+
ref: Ref;
|
|
468
|
+
} & ((props: IExternalComponentProps) => JSX.Element | null) : never;
|
|
469
|
+
loader: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<infer IInnerComponentProps, any> ? (() => (props: IInnerComponentProps) => JSX.Element | null) | (() => Promise<(props: IInnerComponentProps) => JSX.Element | null>) : never;
|
|
470
|
+
}>;
|
|
471
|
+
}>;
|
|
472
|
+
"component:app/core-not-found-error-page": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
473
|
+
kind: "component";
|
|
474
|
+
name: "core-not-found-error-page";
|
|
475
|
+
config: {};
|
|
476
|
+
configInput: {};
|
|
477
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<{
|
|
478
|
+
ref: _backstage_frontend_plugin_api.SwappableComponentRef;
|
|
479
|
+
loader: (() => (props: {}) => JSX.Element | null) | (() => Promise<(props: {}) => JSX.Element | null>);
|
|
480
|
+
}, "core.swappableComponent", {}>;
|
|
481
|
+
inputs: {};
|
|
482
|
+
params: <Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<any>>(params: {
|
|
483
|
+
component: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<any, infer IExternalComponentProps> ? {
|
|
484
|
+
ref: Ref;
|
|
485
|
+
} & ((props: IExternalComponentProps) => JSX.Element | null) : never;
|
|
486
|
+
loader: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<infer IInnerComponentProps, any> ? (() => (props: IInnerComponentProps) => JSX.Element | null) | (() => Promise<(props: IInnerComponentProps) => JSX.Element | null>) : never;
|
|
487
|
+
}) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<{
|
|
488
|
+
component: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<any, infer IExternalComponentProps> ? {
|
|
489
|
+
ref: Ref;
|
|
490
|
+
} & ((props: IExternalComponentProps) => JSX.Element | null) : never;
|
|
491
|
+
loader: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<infer IInnerComponentProps, any> ? (() => (props: IInnerComponentProps) => JSX.Element | null) | (() => Promise<(props: IInnerComponentProps) => JSX.Element | null>) : never;
|
|
492
|
+
}>;
|
|
493
|
+
}>;
|
|
494
|
+
"component:app/core-progress": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
495
|
+
kind: "component";
|
|
496
|
+
name: "core-progress";
|
|
497
|
+
config: {};
|
|
498
|
+
configInput: {};
|
|
499
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<{
|
|
500
|
+
ref: _backstage_frontend_plugin_api.SwappableComponentRef;
|
|
501
|
+
loader: (() => (props: {}) => JSX.Element | null) | (() => Promise<(props: {}) => JSX.Element | null>);
|
|
502
|
+
}, "core.swappableComponent", {}>;
|
|
503
|
+
inputs: {};
|
|
504
|
+
params: <Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<any>>(params: {
|
|
505
|
+
component: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<any, infer IExternalComponentProps> ? {
|
|
506
|
+
ref: Ref;
|
|
507
|
+
} & ((props: IExternalComponentProps) => JSX.Element | null) : never;
|
|
508
|
+
loader: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<infer IInnerComponentProps, any> ? (() => (props: IInnerComponentProps) => JSX.Element | null) | (() => Promise<(props: IInnerComponentProps) => JSX.Element | null>) : never;
|
|
509
|
+
}) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<{
|
|
510
|
+
component: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<any, infer IExternalComponentProps> ? {
|
|
511
|
+
ref: Ref;
|
|
512
|
+
} & ((props: IExternalComponentProps) => JSX.Element | null) : never;
|
|
513
|
+
loader: Ref extends _backstage_frontend_plugin_api.SwappableComponentRef<infer IInnerComponentProps, any> ? (() => (props: IInnerComponentProps) => JSX.Element | null) | (() => Promise<(props: IInnerComponentProps) => JSX.Element | null>) : never;
|
|
514
|
+
}>;
|
|
515
|
+
}>;
|
|
441
516
|
"sign-in-page:app": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
442
517
|
kind: "sign-in-page";
|
|
443
518
|
name: undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InternalExtensionDefinition.esm.js","sources":["../../../../../../../packages/frontend-internal/src/wiring/InternalExtensionDefinition.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 ApiHolder,\n AppNode,\n ExtensionAttachToSpec,\n ExtensionDataValue,\n ExtensionDataRef,\n ExtensionDefinition,\n ExtensionDefinitionParameters,\n ExtensionInput,\n PortableSchema,\n ResolvedExtensionInputs,\n} from '@backstage/frontend-plugin-api';\nimport { OpaqueType } from '@internal/opaque';\n\nexport const OpaqueExtensionDefinition = OpaqueType.create<{\n public: ExtensionDefinition<ExtensionDefinitionParameters>;\n versions:\n | {\n readonly version: 'v1';\n readonly kind?: string;\n readonly namespace?: string;\n readonly name?: string;\n readonly attachTo: ExtensionAttachToSpec;\n readonly disabled: boolean;\n readonly configSchema?: PortableSchema<any, any>;\n readonly inputs: {\n [inputName in string]: {\n $$type: '@backstage/ExtensionInput';\n extensionData: {\n [name in string]: ExtensionDataRef;\n };\n config: { optional: boolean; singleton: boolean };\n };\n };\n readonly output: {\n [name in string]: ExtensionDataRef;\n };\n factory(context: {\n node: AppNode;\n apis: ApiHolder;\n config: object;\n inputs: {\n [inputName in string]: unknown;\n };\n }): {\n [inputName in string]: unknown;\n };\n }\n | {\n readonly version: 'v2';\n readonly kind?: string;\n readonly namespace?: string;\n readonly name?: string;\n readonly attachTo: ExtensionAttachToSpec;\n readonly disabled: boolean;\n readonly configSchema?: PortableSchema<any, any>;\n readonly inputs: {\n [inputName in string]: ExtensionInput<\n ExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n };\n readonly output: Array<ExtensionDataRef>;\n factory(context: {\n node: AppNode;\n apis: ApiHolder;\n config: object;\n inputs: ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput<\n ExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n }>;\n }): Iterable<ExtensionDataValue<any, any>>;\n };\n}>({\n type: '@backstage/ExtensionDefinition',\n versions: ['v1', 'v2'],\n});\n"],"names":[],"mappings":";;AA8ByC,WAAW,MA6DjD,CAAA;AAAA,EACD,IAAM,EAAA,gCAAA;AAAA,EACN,QAAA,EAAU,CAAC,IAAA,EAAM,IAAI;AACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InternalFrontendPlugin.esm.js","sources":["../../../../../../../packages/frontend-internal/src/wiring/InternalFrontendPlugin.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 Extension,\n FeatureFlagConfig,\n FrontendPlugin,\n} from '@backstage/frontend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { OpaqueType } from '@internal/opaque';\n\nexport const OpaqueFrontendPlugin = OpaqueType.create<{\n public: FrontendPlugin;\n versions: {\n readonly version: 'v1';\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n readonly infoOptions?: {\n packageJson?: () => Promise<JsonObject>;\n manifest?: () => Promise<JsonObject>;\n };\n };\n}>({\n type: '@backstage/FrontendPlugin',\n versions: ['v1'],\n});\n"],"names":[],"mappings":";;AAwBoC,WAAW,MAW5C,CAAA;AAAA,EACD,IAAM,EAAA,2BAAA;AAAA,EACN,QAAA,EAAU,CAAC,IAAI;AACjB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OpaqueType } from '../../../opaque-internal/src/OpaqueType.esm.js';
|
|
2
|
+
|
|
3
|
+
const OpaqueSwappableComponentRef = OpaqueType.create({
|
|
4
|
+
versions: ["v1"],
|
|
5
|
+
type: "@backstage/SwappableComponentRef"
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export { OpaqueSwappableComponentRef };
|
|
9
|
+
//# sourceMappingURL=InternalSwappableComponentRef.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InternalSwappableComponentRef.esm.js","sources":["../../../../../../../packages/frontend-internal/src/wiring/InternalSwappableComponentRef.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 { SwappableComponentRef } from '@backstage/frontend-plugin-api';\nimport { OpaqueType } from '@internal/opaque';\n\nexport const OpaqueSwappableComponentRef = OpaqueType.create<{\n public: SwappableComponentRef;\n versions: {\n readonly version: 'v1';\n readonly transformProps?: (props: object) => object;\n readonly defaultComponent: (props: object) => JSX.Element | null;\n };\n}>({\n versions: ['v1'],\n type: '@backstage/SwappableComponentRef',\n});\n"],"names":[],"mappings":";;AAmBa,MAAA,2BAAA,GAA8B,WAAW,MAOnD,CAAA;AAAA,EACD,QAAA,EAAU,CAAC,IAAI,CAAA;AAAA,EACf,IAAM,EAAA;AACR,CAAC;;;;"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
class OpaqueType {
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new opaque type.
|
|
4
|
+
*
|
|
5
|
+
* @param options.type The type identifier of the opaque type
|
|
6
|
+
* @param options.versions The available versions of the opaque type
|
|
7
|
+
* @returns A new opaque type helper
|
|
8
|
+
*/
|
|
9
|
+
static create(options) {
|
|
10
|
+
return new OpaqueType(options.type, new Set(options.versions));
|
|
11
|
+
}
|
|
12
|
+
#type;
|
|
13
|
+
#versions;
|
|
14
|
+
constructor(type, versions) {
|
|
15
|
+
this.#type = type;
|
|
16
|
+
this.#versions = versions;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The internal version of the opaque type, used like this: `typeof MyOpaqueType.TPublic`
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
*
|
|
23
|
+
* This property is only useful for type checking, its runtime value is `undefined`.
|
|
24
|
+
*/
|
|
25
|
+
TPublic = void 0;
|
|
26
|
+
/**
|
|
27
|
+
* The internal version of the opaque type, used like this: `typeof MyOpaqueType.TInternal`
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
*
|
|
31
|
+
* This property is only useful for type checking, its runtime value is `undefined`.
|
|
32
|
+
*/
|
|
33
|
+
TInternal = void 0;
|
|
34
|
+
/**
|
|
35
|
+
* @param value Input value expected to be an instance of this opaque type
|
|
36
|
+
* @returns True if the value matches this opaque type
|
|
37
|
+
*/
|
|
38
|
+
isType = (value) => {
|
|
39
|
+
return this.#isThisInternalType(value);
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* @param value Input value expected to be an instance of this opaque type
|
|
43
|
+
* @throws If the value is not an instance of this opaque type or is of an unsupported version
|
|
44
|
+
* @returns The internal version of the opaque type
|
|
45
|
+
*/
|
|
46
|
+
toInternal = (value) => {
|
|
47
|
+
if (!this.#isThisInternalType(value)) {
|
|
48
|
+
throw new TypeError(
|
|
49
|
+
`Invalid opaque type, expected '${this.#type}', but got '${this.#stringifyUnknown(value)}'`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (!this.#versions.has(value.version)) {
|
|
53
|
+
const versions = Array.from(this.#versions).map(this.#stringifyVersion);
|
|
54
|
+
if (versions.length > 1) {
|
|
55
|
+
versions[versions.length - 1] = `or ${versions[versions.length - 1]}`;
|
|
56
|
+
}
|
|
57
|
+
const expected = versions.length > 2 ? versions.join(", ") : versions.join(" ");
|
|
58
|
+
throw new TypeError(
|
|
59
|
+
`Invalid opaque type instance, got version ${this.#stringifyVersion(
|
|
60
|
+
value.version
|
|
61
|
+
)}, expected ${expected}`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Creates an instance of the opaque type, returning the public type.
|
|
68
|
+
*
|
|
69
|
+
* @param version The version of the instance to create
|
|
70
|
+
* @param value The remaining public and internal properties of the instance
|
|
71
|
+
* @returns An instance of the opaque type
|
|
72
|
+
*/
|
|
73
|
+
createInstance(version, props) {
|
|
74
|
+
return Object.assign(props, {
|
|
75
|
+
$$type: this.#type,
|
|
76
|
+
...version && { version }
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
#isThisInternalType(value) {
|
|
80
|
+
if (value === null || typeof value !== "object") {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return value.$$type === this.#type;
|
|
84
|
+
}
|
|
85
|
+
#stringifyUnknown(value) {
|
|
86
|
+
if (typeof value !== "object") {
|
|
87
|
+
return `<${typeof value}>`;
|
|
88
|
+
}
|
|
89
|
+
if (value === null) {
|
|
90
|
+
return "<null>";
|
|
91
|
+
}
|
|
92
|
+
if ("$$type" in value) {
|
|
93
|
+
return String(value.$$type);
|
|
94
|
+
}
|
|
95
|
+
return String(value);
|
|
96
|
+
}
|
|
97
|
+
#stringifyVersion = (version) => {
|
|
98
|
+
return version ? `'${version}'` : "undefined";
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export { OpaqueType };
|
|
103
|
+
//# sourceMappingURL=OpaqueType.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpaqueType.esm.js","sources":["../../../../../../packages/opaque-internal/src/OpaqueType.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\n// TODO(Rugvip): This lives here temporarily, but should be moved to a more\n// central location. It's useful for backend packages too so we'll need to have\n// it in a common package, but it might also be that we want to make it\n// available publicly too in which case it would make sense to have this be part\n// of @backstage/version-bridge. The problem with exporting it from there is\n// that it would need to be very stable at that point, so it might be a bit\n// early to put it there already.\n\n/**\n * A helper for working with opaque types.\n */\nexport class OpaqueType<\n T extends {\n public: { $$type: string };\n versions: { version: string | undefined };\n },\n> {\n /**\n * Creates a new opaque type.\n *\n * @param options.type The type identifier of the opaque type\n * @param options.versions The available versions of the opaque type\n * @returns A new opaque type helper\n */\n static create<\n T extends {\n public: { $$type: string };\n versions: { version: string | undefined };\n },\n >(options: {\n type: T['public']['$$type'];\n versions: Array<T['versions']['version']>;\n }) {\n return new OpaqueType<T>(options.type, new Set(options.versions));\n }\n\n #type: string;\n #versions: Set<string | undefined>;\n\n private constructor(type: string, versions: Set<string | undefined>) {\n this.#type = type;\n this.#versions = versions;\n }\n\n /**\n * The internal version of the opaque type, used like this: `typeof MyOpaqueType.TPublic`\n *\n * @remarks\n *\n * This property is only useful for type checking, its runtime value is `undefined`.\n */\n TPublic: T['public'] = undefined as any;\n\n /**\n * The internal version of the opaque type, used like this: `typeof MyOpaqueType.TInternal`\n *\n * @remarks\n *\n * This property is only useful for type checking, its runtime value is `undefined`.\n */\n TInternal: T['public'] & T['versions'] = undefined as any;\n\n /**\n * @param value Input value expected to be an instance of this opaque type\n * @returns True if the value matches this opaque type\n */\n isType = (value: unknown): value is T['public'] => {\n return this.#isThisInternalType(value);\n };\n\n /**\n * @param value Input value expected to be an instance of this opaque type\n * @throws If the value is not an instance of this opaque type or is of an unsupported version\n * @returns The internal version of the opaque type\n */\n toInternal = (value: unknown): T['public'] & T['versions'] => {\n if (!this.#isThisInternalType(value)) {\n throw new TypeError(\n `Invalid opaque type, expected '${\n this.#type\n }', but got '${this.#stringifyUnknown(value)}'`,\n );\n }\n\n if (!this.#versions.has(value.version)) {\n const versions = Array.from(this.#versions).map(this.#stringifyVersion);\n if (versions.length > 1) {\n versions[versions.length - 1] = `or ${versions[versions.length - 1]}`;\n }\n const expected =\n versions.length > 2 ? versions.join(', ') : versions.join(' ');\n throw new TypeError(\n `Invalid opaque type instance, got version ${this.#stringifyVersion(\n value.version,\n )}, expected ${expected}`,\n );\n }\n\n return value;\n };\n\n /**\n * Creates an instance of the opaque type, returning the public type.\n *\n * @param version The version of the instance to create\n * @param value The remaining public and internal properties of the instance\n * @returns An instance of the opaque type\n */\n createInstance<\n TVersion extends T['versions']['version'],\n TPublic extends T['public'],\n >(\n version: TVersion,\n props: Omit<T['public'], '$$type'> &\n (T['versions'] extends infer UVersion\n ? UVersion extends { version: TVersion }\n ? Omit<UVersion, 'version'>\n : never\n : never) &\n Object, // & Object to allow for object properties too, e.g. toString()\n ): TPublic {\n return Object.assign(props as object, {\n $$type: this.#type,\n ...(version && { version }),\n }) as unknown as TPublic;\n }\n\n #isThisInternalType(value: unknown): value is T['public'] & T['versions'] {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n return (value as T['public']).$$type === this.#type;\n }\n\n #stringifyUnknown(value: unknown) {\n if (typeof value !== 'object') {\n return `<${typeof value}>`;\n }\n if (value === null) {\n return '<null>';\n }\n if ('$$type' in value) {\n return String(value.$$type);\n }\n return String(value);\n }\n\n #stringifyVersion = (version: string | undefined) => {\n return version ? `'${version}'` : 'undefined';\n };\n}\n"],"names":[],"mappings":"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"}
|
package/dist/plugin.esm.js
CHANGED
|
@@ -6,14 +6,15 @@ import { AppNav } from './extensions/AppNav.esm.js';
|
|
|
6
6
|
import { AppRoot } from './extensions/AppRoot.esm.js';
|
|
7
7
|
import { AppRoutes } from './extensions/AppRoutes.esm.js';
|
|
8
8
|
import { AppThemeApi, DarkTheme, LightTheme } from './extensions/AppThemeApi.esm.js';
|
|
9
|
-
import {
|
|
9
|
+
import { SwappableComponentsApi } from './extensions/SwappableComponentsApi.esm.js';
|
|
10
|
+
import { LegacyComponentsApi } from './extensions/LegacyComponentsApi.esm.js';
|
|
10
11
|
import { IconsApi } from './extensions/IconsApi.esm.js';
|
|
11
12
|
import { FeatureFlagsApi } from './extensions/FeatureFlagsApi.esm.js';
|
|
12
13
|
import { TranslationsApi } from './extensions/TranslationsApi.esm.js';
|
|
13
14
|
import { DefaultSignInPage } from './extensions/DefaultSignInPage.esm.js';
|
|
14
15
|
import { dialogDisplayAppRootElement } from './extensions/DialogDisplay.esm.js';
|
|
15
|
-
import { DefaultProgressComponent, DefaultNotFoundErrorPageComponent, DefaultErrorBoundaryComponent } from './extensions/components.esm.js';
|
|
16
16
|
import { oauthRequestDialogAppRootElement, alertDisplayAppRootElement } from './extensions/elements.esm.js';
|
|
17
|
+
import { Progress, NotFoundErrorPage, ErrorDisplay } from './extensions/components.esm.js';
|
|
17
18
|
import { apis } from './defaultApis.esm.js';
|
|
18
19
|
|
|
19
20
|
const appPlugin = createFrontendPlugin({
|
|
@@ -30,17 +31,18 @@ const appPlugin = createFrontendPlugin({
|
|
|
30
31
|
AppThemeApi,
|
|
31
32
|
DarkTheme,
|
|
32
33
|
LightTheme,
|
|
33
|
-
|
|
34
|
+
SwappableComponentsApi,
|
|
34
35
|
IconsApi,
|
|
35
36
|
FeatureFlagsApi,
|
|
36
37
|
TranslationsApi,
|
|
37
|
-
DefaultProgressComponent,
|
|
38
|
-
DefaultNotFoundErrorPageComponent,
|
|
39
|
-
DefaultErrorBoundaryComponent,
|
|
40
38
|
DefaultSignInPage,
|
|
41
39
|
oauthRequestDialogAppRootElement,
|
|
42
40
|
alertDisplayAppRootElement,
|
|
43
|
-
dialogDisplayAppRootElement
|
|
41
|
+
dialogDisplayAppRootElement,
|
|
42
|
+
Progress,
|
|
43
|
+
NotFoundErrorPage,
|
|
44
|
+
ErrorDisplay,
|
|
45
|
+
LegacyComponentsApi
|
|
44
46
|
]
|
|
45
47
|
});
|
|
46
48
|
|
package/dist/plugin.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.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 { createFrontendPlugin } from '@backstage/frontend-plugin-api';\nimport {\n App,\n AppLanguageApi,\n AppLayout,\n AppNav,\n AppRoot,\n AppRoutes,\n AppThemeApi,\n DarkTheme,\n LightTheme,\n
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.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 { createFrontendPlugin } from '@backstage/frontend-plugin-api';\nimport {\n App,\n AppLanguageApi,\n AppLayout,\n AppNav,\n AppRoot,\n AppRoutes,\n AppThemeApi,\n DarkTheme,\n LightTheme,\n SwappableComponentsApi,\n IconsApi,\n FeatureFlagsApi,\n TranslationsApi,\n oauthRequestDialogAppRootElement,\n alertDisplayAppRootElement,\n DefaultSignInPage,\n dialogDisplayAppRootElement,\n Progress,\n NotFoundErrorPage,\n ErrorDisplay,\n LegacyComponentsApi,\n} from './extensions';\nimport { apis } from './defaultApis';\n\n/** @public */\nexport const appPlugin = createFrontendPlugin({\n pluginId: 'app',\n info: { packageJson: () => import('../package.json') },\n extensions: [\n ...apis,\n App,\n AppLanguageApi,\n AppLayout,\n AppNav,\n AppRoot,\n AppRoutes,\n AppThemeApi,\n DarkTheme,\n LightTheme,\n SwappableComponentsApi,\n IconsApi,\n FeatureFlagsApi,\n TranslationsApi,\n DefaultSignInPage,\n oauthRequestDialogAppRootElement,\n alertDisplayAppRootElement,\n dialogDisplayAppRootElement,\n Progress,\n NotFoundErrorPage,\n ErrorDisplay,\n LegacyComponentsApi,\n ],\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AA2CO,MAAM,YAAY,oBAAqB,CAAA;AAAA,EAC5C,QAAU,EAAA,KAAA;AAAA,EACV,MAAM,EAAE,WAAA,EAAa,MAAM,OAAO,mCAAiB,CAAE,EAAA;AAAA,EACrD,UAAY,EAAA;AAAA,IACV,GAAG,IAAA;AAAA,IACH,GAAA;AAAA,IACA,cAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA,sBAAA;AAAA,IACA,QAAA;AAAA,IACA,eAAA;AAAA,IACA,eAAA;AAAA,IACA,iBAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,2BAAA;AAAA,IACA,QAAA;AAAA,IACA,iBAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "@backstage/plugin-app";
|
|
2
|
-
var version = "0.2.0-next.
|
|
2
|
+
var version = "0.2.0-next.2";
|
|
3
3
|
var backstage = {
|
|
4
4
|
role: "frontend-plugin",
|
|
5
5
|
pluginId: "app",
|
|
@@ -24,6 +24,8 @@ var exports = {
|
|
|
24
24
|
"./alpha": "./src/alpha/index.ts",
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
};
|
|
27
|
+
var main = "src/index.ts";
|
|
28
|
+
var types = "src/index.ts";
|
|
27
29
|
var typesVersions = {
|
|
28
30
|
"*": {
|
|
29
31
|
alpha: [
|
|
@@ -34,8 +36,6 @@ var typesVersions = {
|
|
|
34
36
|
]
|
|
35
37
|
}
|
|
36
38
|
};
|
|
37
|
-
var main = "src/index.ts";
|
|
38
|
-
var types = "src/index.ts";
|
|
39
39
|
var files = [
|
|
40
40
|
"dist"
|
|
41
41
|
];
|
|
@@ -56,11 +56,13 @@ var dependencies = {
|
|
|
56
56
|
"@backstage/plugin-permission-react": "workspace:^",
|
|
57
57
|
"@backstage/theme": "workspace:^",
|
|
58
58
|
"@backstage/types": "workspace:^",
|
|
59
|
+
"@backstage/version-bridge": "workspace:^",
|
|
59
60
|
"@material-ui/core": "^4.9.13",
|
|
60
61
|
"@material-ui/icons": "^4.9.1",
|
|
61
62
|
"@material-ui/lab": "^4.0.0-alpha.61",
|
|
62
63
|
"@react-hookz/web": "^24.0.0",
|
|
63
|
-
"react-use": "^17.2.4"
|
|
64
|
+
"react-use": "^17.2.4",
|
|
65
|
+
zod: "^3.22.4"
|
|
64
66
|
};
|
|
65
67
|
var devDependencies = {
|
|
66
68
|
"@backstage/cli": "workspace:^",
|
|
@@ -97,9 +99,9 @@ var _package = {
|
|
|
97
99
|
license: license,
|
|
98
100
|
sideEffects: sideEffects,
|
|
99
101
|
exports: exports,
|
|
100
|
-
typesVersions: typesVersions,
|
|
101
102
|
main: main,
|
|
102
103
|
types: types,
|
|
104
|
+
typesVersions: typesVersions,
|
|
103
105
|
files: files,
|
|
104
106
|
scripts: scripts,
|
|
105
107
|
dependencies: dependencies,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.json.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"package.json.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-app",
|
|
3
|
-
"version": "0.2.0-next.
|
|
3
|
+
"version": "0.2.0-next.2",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "frontend-plugin",
|
|
6
6
|
"pluginId": "app",
|
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
},
|
|
38
38
|
"./package.json": "./package.json"
|
|
39
39
|
},
|
|
40
|
+
"main": "./dist/index.esm.js",
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
40
42
|
"typesVersions": {
|
|
41
43
|
"*": {
|
|
42
44
|
"alpha": [
|
|
@@ -47,8 +49,6 @@
|
|
|
47
49
|
]
|
|
48
50
|
}
|
|
49
51
|
},
|
|
50
|
-
"main": "./dist/index.esm.js",
|
|
51
|
-
"types": "./dist/index.d.ts",
|
|
52
52
|
"files": [
|
|
53
53
|
"dist"
|
|
54
54
|
],
|
|
@@ -62,23 +62,25 @@
|
|
|
62
62
|
"test": "backstage-cli package test"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@backstage/core-components": "0.17.5-next.
|
|
65
|
+
"@backstage/core-components": "0.17.5-next.2",
|
|
66
66
|
"@backstage/core-plugin-api": "1.10.9",
|
|
67
|
-
"@backstage/frontend-plugin-api": "0.11.0-next.
|
|
67
|
+
"@backstage/frontend-plugin-api": "0.11.0-next.2",
|
|
68
68
|
"@backstage/integration-react": "1.2.9",
|
|
69
69
|
"@backstage/plugin-permission-react": "0.4.36",
|
|
70
70
|
"@backstage/theme": "0.6.8-next.0",
|
|
71
71
|
"@backstage/types": "1.2.1",
|
|
72
|
+
"@backstage/version-bridge": "1.0.11",
|
|
72
73
|
"@material-ui/core": "^4.9.13",
|
|
73
74
|
"@material-ui/icons": "^4.9.1",
|
|
74
75
|
"@material-ui/lab": "^4.0.0-alpha.61",
|
|
75
76
|
"@react-hookz/web": "^24.0.0",
|
|
76
|
-
"react-use": "^17.2.4"
|
|
77
|
+
"react-use": "^17.2.4",
|
|
78
|
+
"zod": "^3.22.4"
|
|
77
79
|
},
|
|
78
80
|
"devDependencies": {
|
|
79
|
-
"@backstage/cli": "0.34.0-next.
|
|
81
|
+
"@backstage/cli": "0.34.0-next.2",
|
|
80
82
|
"@backstage/dev-utils": "1.1.13-next.1",
|
|
81
|
-
"@backstage/frontend-defaults": "0.3.0-next.
|
|
83
|
+
"@backstage/frontend-defaults": "0.3.0-next.3",
|
|
82
84
|
"@backstage/frontend-test-utils": "0.3.5-next.2",
|
|
83
85
|
"@backstage/test-utils": "1.7.11-next.0",
|
|
84
86
|
"@testing-library/jest-dom": "^6.0.0",
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { ApiBlueprint, createExtensionInput, createComponentExtension, componentsApiRef } from '@backstage/frontend-plugin-api';
|
|
2
|
-
import { DefaultComponentsApi } from '../packages/frontend-app-api/src/apis/implementations/ComponentsApi/DefaultComponentsApi.esm.js';
|
|
3
|
-
|
|
4
|
-
const ComponentsApi = ApiBlueprint.makeWithOverrides({
|
|
5
|
-
name: "components",
|
|
6
|
-
inputs: {
|
|
7
|
-
components: createExtensionInput(
|
|
8
|
-
[createComponentExtension.componentDataRef],
|
|
9
|
-
{ replaces: [{ id: "app", input: "components" }] }
|
|
10
|
-
)
|
|
11
|
-
},
|
|
12
|
-
factory: (originalFactory, { inputs }) => {
|
|
13
|
-
return originalFactory(
|
|
14
|
-
(defineParams) => defineParams({
|
|
15
|
-
api: componentsApiRef,
|
|
16
|
-
deps: {},
|
|
17
|
-
factory: () => DefaultComponentsApi.fromComponents(
|
|
18
|
-
inputs.components.map(
|
|
19
|
-
(i) => i.get(createComponentExtension.componentDataRef)
|
|
20
|
-
)
|
|
21
|
-
)
|
|
22
|
-
})
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
export { ComponentsApi };
|
|
28
|
-
//# sourceMappingURL=ComponentsApi.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ComponentsApi.esm.js","sources":["../../src/extensions/ComponentsApi.tsx"],"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 createComponentExtension,\n createExtensionInput,\n ApiBlueprint,\n componentsApiRef,\n} from '@backstage/frontend-plugin-api';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { DefaultComponentsApi } from '../../../../packages/frontend-app-api/src/apis/implementations/ComponentsApi';\n\n/**\n * Contains the shareable components installed into the app.\n */\nexport const ComponentsApi = ApiBlueprint.makeWithOverrides({\n name: 'components',\n inputs: {\n components: createExtensionInput(\n [createComponentExtension.componentDataRef],\n { replaces: [{ id: 'app', input: 'components' }] },\n ),\n },\n factory: (originalFactory, { inputs }) => {\n return originalFactory(defineParams =>\n defineParams({\n api: componentsApiRef,\n deps: {},\n factory: () =>\n DefaultComponentsApi.fromComponents(\n inputs.components.map(i =>\n i.get(createComponentExtension.componentDataRef),\n ),\n ),\n }),\n );\n },\n});\n"],"names":[],"mappings":";;;AA4Ba,MAAA,aAAA,GAAgB,aAAa,iBAAkB,CAAA;AAAA,EAC1D,IAAM,EAAA,YAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,UAAY,EAAA,oBAAA;AAAA,MACV,CAAC,yBAAyB,gBAAgB,CAAA;AAAA,MAC1C,EAAE,UAAU,CAAC,EAAE,IAAI,KAAO,EAAA,KAAA,EAAO,YAAa,EAAC,CAAE;AAAA;AACnD,GACF;AAAA,EACA,OAAS,EAAA,CAAC,eAAiB,EAAA,EAAE,QAAa,KAAA;AACxC,IAAO,OAAA,eAAA;AAAA,MAAgB,kBACrB,YAAa,CAAA;AAAA,QACX,GAAK,EAAA,gBAAA;AAAA,QACL,MAAM,EAAC;AAAA,QACP,OAAA,EAAS,MACP,oBAAqB,CAAA,cAAA;AAAA,UACnB,OAAO,UAAW,CAAA,GAAA;AAAA,YAAI,CACpB,CAAA,KAAA,CAAA,CAAE,GAAI,CAAA,wBAAA,CAAyB,gBAAgB;AAAA;AACjD;AACF,OACH;AAAA,KACH;AAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import Button from '@material-ui/core/Button';
|
|
3
|
-
import { Progress, ErrorPage, ErrorPanel } from '@backstage/core-components';
|
|
4
|
-
import { BrowserRouter, useInRouterContext, MemoryRouter } from 'react-router-dom';
|
|
5
|
-
|
|
6
|
-
function OptionallyWrapInRouter({ children }) {
|
|
7
|
-
if (useInRouterContext()) {
|
|
8
|
-
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
9
|
-
}
|
|
10
|
-
return /* @__PURE__ */ jsx(MemoryRouter, { children });
|
|
11
|
-
}
|
|
12
|
-
const DefaultNotFoundPage = () => /* @__PURE__ */ jsx(ErrorPage, { status: "404", statusMessage: "PAGE NOT FOUND" });
|
|
13
|
-
const DefaultBootErrorPage = ({ step, error }) => {
|
|
14
|
-
let message = "";
|
|
15
|
-
if (step === "load-config") {
|
|
16
|
-
message = `The configuration failed to load, someone should have a look at this error: ${error.message}`;
|
|
17
|
-
} else if (step === "load-chunk") {
|
|
18
|
-
message = `Lazy loaded chunk failed to load, try to reload the page: ${error.message}`;
|
|
19
|
-
}
|
|
20
|
-
return /* @__PURE__ */ jsx(OptionallyWrapInRouter, { children: /* @__PURE__ */ jsx(ErrorPage, { statusMessage: message, stack: error.stack }) });
|
|
21
|
-
};
|
|
22
|
-
const DefaultErrorBoundaryFallback = ({
|
|
23
|
-
error,
|
|
24
|
-
resetError,
|
|
25
|
-
plugin
|
|
26
|
-
}) => {
|
|
27
|
-
return /* @__PURE__ */ jsx(
|
|
28
|
-
ErrorPanel,
|
|
29
|
-
{
|
|
30
|
-
title: `Error in ${plugin?.getId()}`,
|
|
31
|
-
defaultExpanded: true,
|
|
32
|
-
error,
|
|
33
|
-
children: /* @__PURE__ */ jsx(Button, { variant: "outlined", onClick: resetError, children: "Retry" })
|
|
34
|
-
}
|
|
35
|
-
);
|
|
36
|
-
};
|
|
37
|
-
const components = {
|
|
38
|
-
Progress,
|
|
39
|
-
Router: BrowserRouter,
|
|
40
|
-
NotFoundErrorPage: DefaultNotFoundPage,
|
|
41
|
-
BootErrorPage: DefaultBootErrorPage,
|
|
42
|
-
ErrorBoundaryFallback: DefaultErrorBoundaryFallback
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export { OptionallyWrapInRouter, components };
|
|
46
|
-
//# sourceMappingURL=components.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"components.esm.js","sources":["../../../../../../../packages/app-defaults/src/defaults/components.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 { ReactNode } from 'react';\nimport Button from '@material-ui/core/Button';\nimport { ErrorPanel, Progress, ErrorPage } from '@backstage/core-components';\nimport {\n MemoryRouter,\n useInRouterContext,\n BrowserRouter,\n} from 'react-router-dom';\nimport {\n AppComponents,\n BootErrorPageProps,\n ErrorBoundaryFallbackProps,\n} from '@backstage/core-plugin-api';\n\nexport function OptionallyWrapInRouter({ children }: { children: ReactNode }) {\n if (useInRouterContext()) {\n return <>{children}</>;\n }\n return <MemoryRouter>{children}</MemoryRouter>;\n}\n\nconst DefaultNotFoundPage = () => (\n <ErrorPage status=\"404\" statusMessage=\"PAGE NOT FOUND\" />\n);\n\nconst DefaultBootErrorPage = ({ step, error }: BootErrorPageProps) => {\n let message = '';\n if (step === 'load-config') {\n message = `The configuration failed to load, someone should have a look at this error: ${error.message}`;\n } else if (step === 'load-chunk') {\n message = `Lazy loaded chunk failed to load, try to reload the page: ${error.message}`;\n }\n // TODO: figure out a nicer way to handle routing on the error page, when it can be done.\n return (\n <OptionallyWrapInRouter>\n <ErrorPage statusMessage={message} stack={error.stack} />\n </OptionallyWrapInRouter>\n );\n};\n\nconst DefaultErrorBoundaryFallback = ({\n error,\n resetError,\n plugin,\n}: ErrorBoundaryFallbackProps) => {\n return (\n <ErrorPanel\n title={`Error in ${plugin?.getId()}`}\n defaultExpanded\n error={error}\n >\n <Button variant=\"outlined\" onClick={resetError}>\n Retry\n </Button>\n </ErrorPanel>\n );\n};\n\n/**\n * Creates a set of default components to pass along to {@link @backstage/core-app-api#createSpecializedApp}.\n *\n * @public\n */\nexport const components: AppComponents = {\n Progress,\n Router: BrowserRouter,\n NotFoundErrorPage: DefaultNotFoundPage,\n BootErrorPage: DefaultBootErrorPage,\n ErrorBoundaryFallback: DefaultErrorBoundaryFallback,\n};\n"],"names":[],"mappings":";;;;;AA8BgB,SAAA,sBAAA,CAAuB,EAAE,QAAA,EAAqC,EAAA;AAC5E,EAAA,IAAI,oBAAsB,EAAA;AACxB,IAAA,uCAAU,QAAS,EAAA,CAAA;AAAA;AAErB,EAAO,uBAAA,GAAA,CAAC,gBAAc,QAAS,EAAA,CAAA;AACjC;AAEA,MAAM,sBAAsB,sBAC1B,GAAA,CAAC,aAAU,MAAO,EAAA,KAAA,EAAM,eAAc,gBAAiB,EAAA,CAAA;AAGzD,MAAM,oBAAuB,GAAA,CAAC,EAAE,IAAA,EAAM,OAAgC,KAAA;AACpE,EAAA,IAAI,OAAU,GAAA,EAAA;AACd,EAAA,IAAI,SAAS,aAAe,EAAA;AAC1B,IAAU,OAAA,GAAA,CAAA,4EAAA,EAA+E,MAAM,OAAO,CAAA,CAAA;AAAA,GACxG,MAAA,IAAW,SAAS,YAAc,EAAA;AAChC,IAAU,OAAA,GAAA,CAAA,0DAAA,EAA6D,MAAM,OAAO,CAAA,CAAA;AAAA;AAGtF,EACE,uBAAA,GAAA,CAAC,0BACC,QAAC,kBAAA,GAAA,CAAA,SAAA,EAAA,EAAU,eAAe,OAAS,EAAA,KAAA,EAAO,KAAM,CAAA,KAAA,EAAO,CACzD,EAAA,CAAA;AAEJ,CAAA;AAEA,MAAM,+BAA+B,CAAC;AAAA,EACpC,KAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAkC,KAAA;AAChC,EACE,uBAAA,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,KAAO,EAAA,CAAA,SAAA,EAAY,MAAQ,EAAA,KAAA,EAAO,CAAA,CAAA;AAAA,MAClC,eAAe,EAAA,IAAA;AAAA,MACf,KAAA;AAAA,MAEA,8BAAC,MAAO,EAAA,EAAA,OAAA,EAAQ,UAAW,EAAA,OAAA,EAAS,YAAY,QAEhD,EAAA,OAAA,EAAA;AAAA;AAAA,GACF;AAEJ,CAAA;AAOO,MAAM,UAA4B,GAAA;AAAA,EACvC,QAAA;AAAA,EACA,MAAQ,EAAA,aAAA;AAAA,EACR,iBAAmB,EAAA,mBAAA;AAAA,EACnB,aAAe,EAAA,oBAAA;AAAA,EACf,qBAAuB,EAAA;AACzB;;;;"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
class DefaultComponentsApi {
|
|
2
|
-
#components;
|
|
3
|
-
static fromComponents(components) {
|
|
4
|
-
return new DefaultComponentsApi(
|
|
5
|
-
new Map(components.map((entry) => [entry.ref.id, entry.impl]))
|
|
6
|
-
);
|
|
7
|
-
}
|
|
8
|
-
constructor(components) {
|
|
9
|
-
this.#components = components;
|
|
10
|
-
}
|
|
11
|
-
getComponent(ref) {
|
|
12
|
-
const impl = this.#components.get(ref.id);
|
|
13
|
-
if (!impl) {
|
|
14
|
-
throw new Error(`No implementation found for component ref ${ref}`);
|
|
15
|
-
}
|
|
16
|
-
return impl;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export { DefaultComponentsApi };
|
|
21
|
-
//# sourceMappingURL=DefaultComponentsApi.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultComponentsApi.esm.js","sources":["../../../../../../../../../packages/frontend-app-api/src/apis/implementations/ComponentsApi/DefaultComponentsApi.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 { ComponentType } from 'react';\nimport {\n ComponentRef,\n ComponentsApi,\n createComponentExtension,\n} from '@backstage/frontend-plugin-api';\n\n/**\n * Implementation for the {@linkComponentApi}\n *\n * @internal\n */\nexport class DefaultComponentsApi implements ComponentsApi {\n #components: Map<string, ComponentType<any>>;\n\n static fromComponents(\n components: Array<typeof createComponentExtension.componentDataRef.T>,\n ) {\n return new DefaultComponentsApi(\n new Map(components.map(entry => [entry.ref.id, entry.impl])),\n );\n }\n\n constructor(components: Map<string, any>) {\n this.#components = components;\n }\n\n getComponent<T extends {}>(ref: ComponentRef<T>): ComponentType<T> {\n const impl = this.#components.get(ref.id);\n if (!impl) {\n throw new Error(`No implementation found for component ref ${ref}`);\n }\n return impl;\n }\n}\n"],"names":[],"mappings":"AA4BO,MAAM,oBAA8C,CAAA;AAAA,EACzD,WAAA;AAAA,EAEA,OAAO,eACL,UACA,EAAA;AACA,IAAA,OAAO,IAAI,oBAAA;AAAA,MACT,IAAI,GAAA,CAAI,UAAW,CAAA,GAAA,CAAI,CAAS,KAAA,KAAA,CAAC,KAAM,CAAA,GAAA,CAAI,EAAI,EAAA,KAAA,CAAM,IAAI,CAAC,CAAC;AAAA,KAC7D;AAAA;AACF,EAEA,YAAY,UAA8B,EAAA;AACxC,IAAA,IAAA,CAAK,WAAc,GAAA,UAAA;AAAA;AACrB,EAEA,aAA2B,GAAwC,EAAA;AACjE,IAAA,MAAM,IAAO,GAAA,IAAA,CAAK,WAAY,CAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AACxC,IAAA,IAAI,CAAC,IAAM,EAAA;AACT,MAAA,MAAM,IAAI,KAAA,CAAM,CAA6C,0CAAA,EAAA,GAAG,CAAE,CAAA,CAAA;AAAA;AAEpE,IAAO,OAAA,IAAA;AAAA;AAEX;;;;"}
|