@backstage/frontend-dev-utils 0.0.0-nightly-20260317031259
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 +15 -0
- package/README.md +19 -0
- package/dist/BuiCss.esm.js +6 -0
- package/dist/BuiCss.esm.js.map +1 -0
- package/dist/createDevApp.esm.js +57 -0
- package/dist/createDevApp.esm.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -0
- package/package.json +73 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @backstage/frontend-dev-utils
|
|
2
|
+
|
|
3
|
+
## 0.0.0-nightly-20260317031259
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- c25532a: Added `@backstage/frontend-dev-utils`, a new package that provides a minimal helper for wiring up a development app for frontend plugins using the new frontend system. It exports a `createDevApp` function that handles creating and rendering a development app from a `dev/` entry point. The dev app automatically bypasses the sign-in page and loads the `@backstage/ui` CSS. The options interface accepts `features` together with route bindings through `bindRoutes`.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @backstage/frontend-plugin-api@0.0.0-nightly-20260317031259
|
|
13
|
+
- @backstage/ui@0.0.0-nightly-20260317031259
|
|
14
|
+
- @backstage/plugin-app@0.0.0-nightly-20260317031259
|
|
15
|
+
- @backstage/frontend-defaults@0.0.0-nightly-20260317031259
|
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @backstage/frontend-dev-utils
|
|
2
|
+
|
|
3
|
+
Utilities for developing Backstage frontend plugins using the new frontend system.
|
|
4
|
+
|
|
5
|
+
This package provides a minimal helper for wiring up a development app from a `dev/` entry point, making it easy to run and test frontend plugins in isolation.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Install the package via Yarn:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
cd plugins/<plugin> # if within a monorepo
|
|
13
|
+
yarn add -D @backstage/frontend-dev-utils
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Documentation
|
|
17
|
+
|
|
18
|
+
- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md)
|
|
19
|
+
- [Backstage Documentation](https://backstage.io/docs)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BuiCss.esm.js","sources":["../src/BuiCss.tsx"],"sourcesContent":["/*\n * Copyright 2026 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// This ensures that dev apps always have the BUI CSS loaded.\n// eslint-disable-next-line @backstage/no-ui-css-imports-in-non-frontend\nimport '@backstage/ui/css/styles.css';\n\n/**\n * Placeholder component to allow lazy loading of the BUI CSS import. This\n * ensures that we don't load the CSS as soon as anyone imports this package.\n */\nexport default () => null;\n"],"names":[],"mappings":";;AAwBA,aAAe,MAAM,IAAA;;;;"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createApp } from '@backstage/frontend-defaults';
|
|
3
|
+
import appPlugin from '@backstage/plugin-app';
|
|
4
|
+
import { lazy, Suspense } from 'react';
|
|
5
|
+
import 'react-dom';
|
|
6
|
+
|
|
7
|
+
const appPluginOverride = appPlugin.withOverrides({
|
|
8
|
+
extensions: [
|
|
9
|
+
appPlugin.getExtension("sign-in-page:app").override({
|
|
10
|
+
disabled: true
|
|
11
|
+
})
|
|
12
|
+
]
|
|
13
|
+
});
|
|
14
|
+
const BuiCss = lazy(() => import('./BuiCss.esm.js'));
|
|
15
|
+
let ReactDOMPromise;
|
|
16
|
+
if (process.env.HAS_REACT_DOM_CLIENT) {
|
|
17
|
+
ReactDOMPromise = import('react-dom/client');
|
|
18
|
+
} else {
|
|
19
|
+
ReactDOMPromise = import('react-dom');
|
|
20
|
+
}
|
|
21
|
+
function getRootElement() {
|
|
22
|
+
const rootElement = document.getElementById("root");
|
|
23
|
+
if (!rootElement) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
"Could not find the dev app root element '#root'; make sure your dev entry HTML contains a root element with that id."
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return rootElement;
|
|
29
|
+
}
|
|
30
|
+
function createDevApp(options) {
|
|
31
|
+
const rootElement = getRootElement();
|
|
32
|
+
const { features, bindRoutes } = options;
|
|
33
|
+
const devFeatures = [
|
|
34
|
+
appPluginOverride,
|
|
35
|
+
...features
|
|
36
|
+
];
|
|
37
|
+
const appOptions = {
|
|
38
|
+
bindRoutes,
|
|
39
|
+
features: devFeatures
|
|
40
|
+
};
|
|
41
|
+
const app = createApp(appOptions);
|
|
42
|
+
const AppRoot = app.createRoot();
|
|
43
|
+
ReactDOMPromise.then((ReactDOM) => {
|
|
44
|
+
const rootNode = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
45
|
+
/* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(BuiCss, {}) }),
|
|
46
|
+
AppRoot
|
|
47
|
+
] });
|
|
48
|
+
if ("createRoot" in ReactDOM) {
|
|
49
|
+
ReactDOM.createRoot(rootElement).render(rootNode);
|
|
50
|
+
} else {
|
|
51
|
+
ReactDOM.render(rootNode, rootElement);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { createDevApp };
|
|
57
|
+
//# sourceMappingURL=createDevApp.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDevApp.esm.js","sources":["../src/createDevApp.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 FrontendFeature,\n FrontendFeatureLoader,\n} from '@backstage/frontend-plugin-api';\nimport { createApp, CreateAppOptions } from '@backstage/frontend-defaults';\nimport appPlugin from '@backstage/plugin-app';\nimport { Suspense, lazy } from 'react';\nimport 'react-dom';\n\ntype AppPluginWithSimpleOverrides = {\n withOverrides(options: { extensions: unknown[] }): FrontendFeature;\n};\n\n// Collapse the deeply nested override types to avoid excessive instantiation.\nconst appPluginOverride = (\n appPlugin as unknown as AppPluginWithSimpleOverrides\n).withOverrides({\n extensions: [\n appPlugin.getExtension('sign-in-page:app').override({\n disabled: true,\n }),\n ],\n});\n\nconst BuiCss = lazy(() => import('./BuiCss'));\n\nlet ReactDOMPromise: Promise<\n typeof import('react-dom') | typeof import('react-dom/client')\n>;\nif (process.env.HAS_REACT_DOM_CLIENT) {\n ReactDOMPromise = import('react-dom/client');\n} else {\n ReactDOMPromise = import('react-dom');\n}\n\n/**\n * Options for {@link createDevApp}.\n *\n * @public\n */\nexport interface CreateDevAppOptions {\n /**\n * The list of features to load in the dev app.\n */\n features: (FrontendFeature | FrontendFeatureLoader)[];\n\n /**\n * Allows for the binding of plugins' external route refs within the dev app.\n */\n bindRoutes?: CreateAppOptions['bindRoutes'];\n}\n\nfunction getRootElement(): HTMLElement {\n const rootElement = document.getElementById('root');\n\n if (!rootElement) {\n throw new Error(\n \"Could not find the dev app root element '#root'; make sure your dev entry HTML contains a root element with that id.\",\n );\n }\n\n return rootElement;\n}\n\n/**\n * Creates and renders a minimal development app for the new frontend system.\n *\n * @example\n * ```tsx\n * // dev/index.ts\n * import { createDevApp } from '@backstage/frontend-dev-utils';\n * import myPlugin from '../src';\n *\n * createDevApp({ features: [myPlugin] });\n * ```\n *\n * @public\n */\nexport function createDevApp(options: CreateDevAppOptions): void {\n const rootElement = getRootElement();\n const { features, bindRoutes } = options;\n const devFeatures: CreateAppOptions['features'] = [\n appPluginOverride,\n ...features,\n ];\n const appOptions: CreateAppOptions = {\n bindRoutes,\n features: devFeatures,\n };\n const app = createApp(appOptions);\n const AppRoot = app.createRoot();\n\n ReactDOMPromise.then(ReactDOM => {\n const rootNode = (\n <>\n <Suspense fallback={null}>\n <BuiCss />\n </Suspense>\n {AppRoot}\n </>\n );\n\n if ('createRoot' in ReactDOM) {\n ReactDOM.createRoot(rootElement).render(rootNode);\n } else {\n ReactDOM.render(rootNode, rootElement);\n }\n });\n}\n"],"names":[],"mappings":";;;;;;AA8BA,MAAM,iBAAA,GACJ,UACA,aAAA,CAAc;AAAA,EACd,UAAA,EAAY;AAAA,IACV,SAAA,CAAU,YAAA,CAAa,kBAAkB,CAAA,CAAE,QAAA,CAAS;AAAA,MAClD,QAAA,EAAU;AAAA,KACX;AAAA;AAEL,CAAC,CAAA;AAED,MAAM,MAAA,GAAS,IAAA,CAAK,MAAM,OAAO,iBAAU,CAAC,CAAA;AAE5C,IAAI,eAAA;AAGJ,IAAI,OAAA,CAAQ,IAAI,oBAAA,EAAsB;AACpC,EAAA,eAAA,GAAkB,OAAO,kBAAkB,CAAA;AAC7C,CAAA,MAAO;AACL,EAAA,eAAA,GAAkB,OAAO,WAAW,CAAA;AACtC;AAmBA,SAAS,cAAA,GAA8B;AACrC,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,cAAA,CAAe,MAAM,CAAA;AAElD,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO,WAAA;AACT;AAgBO,SAAS,aAAa,OAAA,EAAoC;AAC/D,EAAA,MAAM,cAAc,cAAA,EAAe;AACnC,EAAA,MAAM,EAAE,QAAA,EAAU,UAAA,EAAW,GAAI,OAAA;AACjC,EAAA,MAAM,WAAA,GAA4C;AAAA,IAChD,iBAAA;AAAA,IACA,GAAG;AAAA,GACL;AACA,EAAA,MAAM,UAAA,GAA+B;AAAA,IACnC,UAAA;AAAA,IACA,QAAA,EAAU;AAAA,GACZ;AACA,EAAA,MAAM,GAAA,GAAM,UAAU,UAAU,CAAA;AAChC,EAAA,MAAM,OAAA,GAAU,IAAI,UAAA,EAAW;AAE/B,EAAA,eAAA,CAAgB,KAAK,CAAA,QAAA,KAAY;AAC/B,IAAA,MAAM,2BACJ,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAA,EAAA,EAAS,QAAA,EAAU,IAAA,EAClB,QAAA,kBAAA,GAAA,CAAC,UAAO,CAAA,EACV,CAAA;AAAA,MACC;AAAA,KAAA,EACH,CAAA;AAGF,IAAA,IAAI,gBAAgB,QAAA,EAAU;AAC5B,MAAA,QAAA,CAAS,UAAA,CAAW,WAAW,CAAA,CAAE,MAAA,CAAO,QAAQ,CAAA;AAAA,IAClD,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,MAAA,CAAO,UAAU,WAAW,CAAA;AAAA,IACvC;AAAA,EACF,CAAC,CAAA;AACH;;;;"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { FrontendFeature, FrontendFeatureLoader } from '@backstage/frontend-plugin-api';
|
|
2
|
+
import { CreateAppOptions } from '@backstage/frontend-defaults';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Options for {@link createDevApp}.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
interface CreateDevAppOptions {
|
|
10
|
+
/**
|
|
11
|
+
* The list of features to load in the dev app.
|
|
12
|
+
*/
|
|
13
|
+
features: (FrontendFeature | FrontendFeatureLoader)[];
|
|
14
|
+
/**
|
|
15
|
+
* Allows for the binding of plugins' external route refs within the dev app.
|
|
16
|
+
*/
|
|
17
|
+
bindRoutes?: CreateAppOptions['bindRoutes'];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Creates and renders a minimal development app for the new frontend system.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* // dev/index.ts
|
|
25
|
+
* import { createDevApp } from '@backstage/frontend-dev-utils';
|
|
26
|
+
* import myPlugin from '../src';
|
|
27
|
+
*
|
|
28
|
+
* createDevApp({ features: [myPlugin] });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
declare function createDevApp(options: CreateDevAppOptions): void;
|
|
34
|
+
|
|
35
|
+
export { createDevApp };
|
|
36
|
+
export type { CreateDevAppOptions };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@backstage/frontend-dev-utils",
|
|
3
|
+
"version": "0.0.0-nightly-20260317031259",
|
|
4
|
+
"description": "Utilities for developing Backstage frontend plugins using the new frontend system.",
|
|
5
|
+
"backstage": {
|
|
6
|
+
"role": "web-library"
|
|
7
|
+
},
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public",
|
|
10
|
+
"main": "dist/index.esm.js",
|
|
11
|
+
"types": "dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"backstage"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://backstage.io",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/backstage/backstage",
|
|
20
|
+
"directory": "packages/frontend-dev-utils"
|
|
21
|
+
},
|
|
22
|
+
"license": "Apache-2.0",
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"main": "dist/index.esm.js",
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "backstage-cli package build",
|
|
31
|
+
"clean": "backstage-cli package clean",
|
|
32
|
+
"lint": "backstage-cli package lint",
|
|
33
|
+
"prepack": "backstage-cli package prepack",
|
|
34
|
+
"postpack": "backstage-cli package postpack",
|
|
35
|
+
"start": "backstage-cli package start",
|
|
36
|
+
"test": "backstage-cli package test"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@backstage/frontend-defaults": "0.0.0-nightly-20260317031259",
|
|
40
|
+
"@backstage/frontend-plugin-api": "0.0.0-nightly-20260317031259",
|
|
41
|
+
"@backstage/plugin-app": "0.0.0-nightly-20260317031259",
|
|
42
|
+
"@backstage/ui": "0.0.0-nightly-20260317031259"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@backstage/cli": "0.0.0-nightly-20260317031259",
|
|
46
|
+
"@backstage/test-utils": "0.0.0-nightly-20260317031259",
|
|
47
|
+
"@testing-library/jest-dom": "^6.0.0",
|
|
48
|
+
"@testing-library/react": "^16.0.0",
|
|
49
|
+
"@types/react": "^18.0.0",
|
|
50
|
+
"react": "^18.0.2",
|
|
51
|
+
"react-dom": "^18.0.2",
|
|
52
|
+
"react-router-dom": "^6.30.2"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"@types/react": "^17.0.0 || ^18.0.0",
|
|
56
|
+
"react": "^17.0.0 || ^18.0.0",
|
|
57
|
+
"react-dom": "^17.0.0 || ^18.0.0",
|
|
58
|
+
"react-router-dom": "^6.30.2"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"@types/react": {
|
|
62
|
+
"optional": true
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"typesVersions": {
|
|
66
|
+
"*": {
|
|
67
|
+
"package.json": [
|
|
68
|
+
"package.json"
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"module": "./dist/index.esm.js"
|
|
73
|
+
}
|