feat(eslint): relax frontend imports for nfs

allow frontend plugins to import from other frontend plugins with same
plugin id to allow plugin overrides without unnecessary eslint warning.

relates to #31372

Signed-off-by: Hellgren Heikki <heikki.hellgren@op.fi>
This commit is contained in:
Hellgren Heikki
2025-10-09 15:11:17 +03:00
parent 9f6f46d234
commit a1dae7180d
7 changed files with 65 additions and 4 deletions
@@ -1,6 +1,25 @@
# @backstage/no-mixed-plugin-imports
Disallow mixed imports between backstage plugins.
This rule ensures that imports between Backstage plugins are consistent with their intended usage.
The rule checks the `backstage.role` field in the `package.json` of both the importing and target packages to determine if they are compatible.
Plugin roles include:
- `frontend-plugin` (or `frontend` for short)
- `backend-plugin` (or `backend` for short)
- `web-library` (or `react` for short)
- `node-library` (or `node` for short)
- `common-library` (or `common` for short)
Prohibited imports include:
- A `frontend` plugin importing directly from another `frontend`, `backend`, or `node` package. Instead, it should import from the corresponding `react` or `common` package.
- With an exception with the new frontend system where frontend plugins with the same plugin id are allowed to import from each other.
- A `backend` plugin importing directly from another `backend`, `frontend`, or `react` package. Instead, it should import from the corresponding `node` or `common` package.
- A `react` package importing from `frontend`, `backend`, or `node` packages.
- A `node` package importing from `frontend`, `backend`, or `react` packages
- A `common` package importing directly from any other plugin package.
## Usage
+1 -1
View File
@@ -21,7 +21,7 @@ const manypkg = require('@manypkg/get-packages');
/**
* @typedef ExtendedPackage
* @type {import('@manypkg/get-packages').Package & { packageJson: { exports?: Record<string, string>, files?: Array<string>, backstage?: { inline?: boolean, role?: string } }}} packageJson
* @type {import('@manypkg/get-packages').Package & { packageJson: { exports?: Record<string, string>, files?: Array<string>, backstage?: { inline?: boolean, role?: string, pluginId?: string } }}} packageJson
*/
/**
@@ -146,11 +146,24 @@ module.exports = {
}
const sourceRole = pkg.packageJson.backstage?.role;
const sourcePluginId = pkg.packageJson.backstage?.pluginId;
const targetRole = targetPackage.packageJson.backstage?.role;
const targetPluginId = targetPackage.packageJson.backstage?.pluginId;
if (!sourceRole || !targetRole) {
return;
}
// Allow frontend plugins to import from other frontend plugins with the same pluginId for NFS
if (
sourceRole === 'frontend-plugin' &&
targetRole === 'frontend-plugin' &&
sourcePluginId &&
targetPluginId &&
sourcePluginId === targetPluginId
) {
return;
}
if (
roleRules.some(
rule =>
@@ -0,0 +1,19 @@
{
"name": "@internal/bar-override",
"backstage": {
"role": "frontend-plugin",
"pluginId": "bar"
},
"exports": {
".": "./src/index.ts",
"./BarPage": "./src/components/Bar.tsx",
"./package.json": "./package.json"
},
"dependencies": {
"inline-dep": "*",
"react-router": "*"
},
"devDependencies": {
"react-router-dom": "*"
}
}
@@ -1,7 +1,8 @@
{
"name": "@internal/bar",
"backstage": {
"role": "frontend-plugin"
"role": "frontend-plugin",
"pluginId": "bar"
},
"exports": {
".": "./src/index.ts",
@@ -1,7 +1,8 @@
{
"name": "@internal/foo",
"backstage": {
"role": "frontend-plugin"
"role": "frontend-plugin",
"pluginId": "foo"
},
"files": [
"dist",