From 7187f2953edce88e2e485a1784e3b0de66929c51 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Oct 2023 17:33:44 +0200 Subject: [PATCH] cli: update package detection filtering logic to only consider package name Signed-off-by: Patrik Oldsberg --- .changeset/twelve-mirrors-brush.md | 5 ++ .../cli/src/lib/bundler/packageDetection.ts | 83 +++++++++++-------- 2 files changed, 55 insertions(+), 33 deletions(-) create mode 100644 .changeset/twelve-mirrors-brush.md diff --git a/.changeset/twelve-mirrors-brush.md b/.changeset/twelve-mirrors-brush.md new file mode 100644 index 0000000000..90725b5ec4 --- /dev/null +++ b/.changeset/twelve-mirrors-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +The experimental package discovery will now always use the package name for include and exclude filtering, rather than the full module id. Entries pointing to a subpath export will now instead have an `export` field specifying the subpath that the import is from. diff --git a/packages/cli/src/lib/bundler/packageDetection.ts b/packages/cli/src/lib/bundler/packageDetection.ts index 10686f7c86..2095fe23e7 100644 --- a/packages/cli/src/lib/bundler/packageDetection.ts +++ b/packages/cli/src/lib/bundler/packageDetection.ts @@ -15,7 +15,7 @@ */ import { BackstagePackageJson } from '@backstage/cli-node'; -import { Config } from '@backstage/config'; +import { Config, ConfigReader } from '@backstage/config'; import chokidar from 'chokidar'; import fs from 'fs-extra'; import { join as joinPath, resolve as resolvePath } from 'path'; @@ -45,9 +45,19 @@ function readPackageDetectionConfig( return {}; } + if (typeof packages !== 'object' || Array.isArray(packages)) { + throw new Error( + "Invalid config at 'app.experimental.packages', expected object", + ); + } + const packagesConfig = new ConfigReader( + packages, + 'app.experimental.packages', + ); + return { - include: config.getOptionalStringArray('app.experimental.packages.include'), - exclude: config.getOptionalStringArray('app.experimental.packages.exclude'), + include: packagesConfig.getOptionalStringArray('include'), + exclude: packagesConfig.getOptionalStringArray('exclude'), }; } @@ -59,40 +69,47 @@ async function detectPackages( resolvePath(targetPath, 'package.json'), ); - return Object.keys(pkg.dependencies ?? {}) - .flatMap(depName => { - const depPackageJson: BackstagePackageJson = require(require.resolve( - `${depName}/package.json`, - { paths: [targetPath] }, - )); - if ( - ['frontend-plugin', 'frontend-plugin-module'].includes( - depPackageJson.backstage?.role ?? '', - ) - ) { - // Include alpha entry point if available. If there's no default export it will be ignored - const exp = depPackageJson.exports; - if (exp && typeof exp === 'object' && './alpha' in exp) { - return [depName, `${depName}/alpha`]; - } - return [depName]; - } + return Object.keys(pkg.dependencies ?? {}).flatMap(depName => { + if (exclude?.includes(depName)) { return []; - }) - .filter(name => { - if (exclude?.includes(name)) { - return false; + } + if (include && !include.includes(depName)) { + return []; + } + + const depPackageJson: BackstagePackageJson = require(require.resolve( + `${depName}/package.json`, + { paths: [targetPath] }, + )); + if ( + ['frontend-plugin', 'frontend-plugin-module'].includes( + depPackageJson.backstage?.role ?? '', + ) + ) { + // Include alpha entry point if available. If there's no default export it will be ignored + const exp = depPackageJson.exports; + if (exp && typeof exp === 'object' && './alpha' in exp) { + return [ + { name: depName, import: depName }, + { name: depName, export: './alpha', import: `${depName}/alpha` }, + ]; } - if (include && !include.includes(name)) { - return false; - } - return true; - }); + return [{ name: depName, import: depName }]; + } + return []; + }); } -async function writeDetectedPackagesModule(packageNames: string[]) { - const requirePackageScript = packageNames - ?.map(pkg => `{ name: '${pkg}', default: require('${pkg}').default }`) +async function writeDetectedPackagesModule( + pkgs: { name: string; export?: string; import: string }[], +) { + const requirePackageScript = pkgs + ?.map( + pkg => + `{ name: ${JSON.stringify(pkg.name)}, export: ${JSON.stringify( + pkg.export, + )}, default: require('${pkg.import}').default }`, + ) .join(','); await fs.writeFile(