diff --git a/.changeset/cli-internalize-lib-modules.md b/.changeset/cli-internalize-lib-modules.md new file mode 100644 index 0000000000..f9ef219a3a --- /dev/null +++ b/.changeset/cli-internalize-lib-modules.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Internal refactor to move shared utilities into their consuming modules, reducing cross-module dependencies. diff --git a/packages/cli/src/modules/build/commands/package/pack.ts b/packages/cli/src/modules/build/commands/package/pack.ts index 737b4b6931..67ef7bca8b 100644 --- a/packages/cli/src/modules/build/commands/package/pack.ts +++ b/packages/cli/src/modules/build/commands/package/pack.ts @@ -22,7 +22,7 @@ import { targetPaths } from '@backstage/cli-common'; import fs from 'fs-extra'; import { publishPreflightCheck } from '../../lib/publishing'; -import { createTypeDistProject } from '../../../../lib/typeDistProject'; +import { createTypeDistProject } from '../../../build/lib/typeDistProject'; export const pre = async () => { publishPreflightCheck({ diff --git a/packages/cli/src/modules/build/commands/repo/build.ts b/packages/cli/src/modules/build/commands/repo/build.ts index dd65e926b2..59d0a839e4 100644 --- a/packages/cli/src/modules/build/commands/repo/build.ts +++ b/packages/cli/src/modules/build/commands/repo/build.ts @@ -28,7 +28,7 @@ import { } from '@backstage/cli-node'; import { buildFrontend } from '../../lib/buildFrontend'; import { buildBackend } from '../../lib/buildBackend'; -import { createScriptOptionsParser } from '../../../../lib/optionsParser'; +import { createScriptOptionsParser } from '../../lib/optionsParser'; export async function command(opts: OptionValues, cmd: Command): Promise { let packages = await PackageGraph.listTargetPackages(); diff --git a/packages/cli/src/modules/build/index.ts b/packages/cli/src/modules/build/index.ts index 277993d252..30a9b3a19e 100644 --- a/packages/cli/src/modules/build/index.ts +++ b/packages/cli/src/modules/build/index.ts @@ -17,7 +17,13 @@ import { Command, Option } from 'commander'; import { createCliPlugin } from '../../wiring/factory'; import { lazy } from '../../wiring/lazy'; -import { configOption } from '../config'; + +const configOption = [ + '--config ', + 'Config files to load instead of app-config.yaml', + (opt: string, opts: string[]) => (opts ? [...opts, opt] : [opt]), + Array(), +] as const; export function registerPackageCommands(command: Command) { command diff --git a/packages/cli/src/lib/__testUtils__/createFeatureEnvironment.ts b/packages/cli/src/modules/build/lib/__testUtils__/createFeatureEnvironment.ts similarity index 100% rename from packages/cli/src/lib/__testUtils__/createFeatureEnvironment.ts rename to packages/cli/src/modules/build/lib/__testUtils__/createFeatureEnvironment.ts diff --git a/packages/cli/src/modules/build/lib/bundler/moduleFederation.ts b/packages/cli/src/modules/build/lib/bundler/moduleFederation.ts index 307cb5cebc..69e1415b5d 100644 --- a/packages/cli/src/modules/build/lib/bundler/moduleFederation.ts +++ b/packages/cli/src/modules/build/lib/bundler/moduleFederation.ts @@ -20,7 +20,7 @@ import { readEntryPoints } from '../entryPoints'; import { createTypeDistProject, getEntryPointDefaultFeatureType, -} from '../../../../lib/typeDistProject'; +} from '../typeDistProject'; import { BACKSTAGE_RUNTIME_SHARED_DEPENDENCIES_GLOBAL, defaultRemoteSharedDependencies, diff --git a/packages/cli/src/lib/optionsParser.ts b/packages/cli/src/modules/build/lib/optionsParser.ts similarity index 100% rename from packages/cli/src/lib/optionsParser.ts rename to packages/cli/src/modules/build/lib/optionsParser.ts diff --git a/packages/cli/src/modules/build/lib/packager/createDistWorkspace.ts b/packages/cli/src/modules/build/lib/packager/createDistWorkspace.ts index 50fb0f4e31..9f63525186 100644 --- a/packages/cli/src/modules/build/lib/packager/createDistWorkspace.ts +++ b/packages/cli/src/modules/build/lib/packager/createDistWorkspace.ts @@ -44,7 +44,7 @@ import { PackageGraphNode, runConcurrentTasks, } from '@backstage/cli-node'; -import { createTypeDistProject } from '../../../../lib/typeDistProject'; +import { createTypeDistProject } from '../typeDistProject'; // These packages aren't safe to pack in parallel since the CLI depends on them const UNSAFE_PACKAGES = [ diff --git a/packages/cli/src/modules/build/lib/packager/productionPack.ts b/packages/cli/src/modules/build/lib/packager/productionPack.ts index ce9f15388c..55eb6edc48 100644 --- a/packages/cli/src/modules/build/lib/packager/productionPack.ts +++ b/packages/cli/src/modules/build/lib/packager/productionPack.ts @@ -19,7 +19,7 @@ import npmPackList from 'npm-packlist'; import { resolve as resolvePath, posix as posixPath } from 'node:path'; import { BackstagePackageJson } from '@backstage/cli-node'; import { readEntryPoints } from '../entryPoints'; -import { getEntryPointDefaultFeatureType } from '../../../../lib/typeDistProject'; +import { getEntryPointDefaultFeatureType } from '../typeDistProject'; import { Project } from 'ts-morph'; const PKG_PATH = 'package.json'; diff --git a/packages/cli/src/lib/typeDistProject.test.ts b/packages/cli/src/modules/build/lib/typeDistProject.test.ts similarity index 100% rename from packages/cli/src/lib/typeDistProject.test.ts rename to packages/cli/src/modules/build/lib/typeDistProject.test.ts diff --git a/packages/cli/src/lib/typeDistProject.ts b/packages/cli/src/modules/build/lib/typeDistProject.ts similarity index 100% rename from packages/cli/src/lib/typeDistProject.ts rename to packages/cli/src/modules/build/lib/typeDistProject.ts diff --git a/packages/cli/src/modules/lint/commands/repo/lint.ts b/packages/cli/src/modules/lint/commands/repo/lint.ts index dafcff45c6..d0b4f6f37e 100644 --- a/packages/cli/src/modules/lint/commands/repo/lint.ts +++ b/packages/cli/src/modules/lint/commands/repo/lint.ts @@ -27,7 +27,7 @@ import { } from '@backstage/cli-node'; import { targetPaths } from '@backstage/cli-common'; -import { createScriptOptionsParser } from '../../../../lib/optionsParser'; +import { createScriptOptionsParser } from '../../lib/optionsParser'; import { SuccessCache } from '../../../../lib/cache/SuccessCache'; function depCount(pkg: BackstagePackageJson) { diff --git a/packages/cli/src/modules/lint/lib/optionsParser.ts b/packages/cli/src/modules/lint/lib/optionsParser.ts new file mode 100644 index 0000000000..45c7eac0aa --- /dev/null +++ b/packages/cli/src/modules/lint/lib/optionsParser.ts @@ -0,0 +1,70 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Command } from 'commander'; + +export function createScriptOptionsParser( + anyCmd: Command, + commandPath: string[], +) { + // Regardless of what command instance is passed in we want to find + // the root command and resolve the path from there + let rootCmd = anyCmd; + while (rootCmd.parent) { + rootCmd = rootCmd.parent; + } + + // Now find the command that was requested + let targetCmd = rootCmd as Command | undefined; + for (const name of commandPath) { + targetCmd = targetCmd?.commands.find(c => c.name() === name) as + | Command + | undefined; + } + + if (!targetCmd) { + throw new Error( + `Could not find package command '${commandPath.join(' ')}'`, + ); + } + const cmd = targetCmd; + + const expectedScript = `backstage-cli ${commandPath.join(' ')}`; + + return (scriptStr?: string) => { + if (!scriptStr || !scriptStr.startsWith(expectedScript)) { + return undefined; + } + + const argsStr = scriptStr.slice(expectedScript.length).trim(); + + // Can't clone or copy or even use commands as prototype, so we mutate + // the necessary members instead, and then reset them once we're done + const currentOpts = (cmd as any)._optionValues; + const currentStore = (cmd as any)._storeOptionsAsProperties; + + const result: Record = {}; + (cmd as any)._storeOptionsAsProperties = false; + (cmd as any)._optionValues = result; + + // Triggers the writing of options to the result object + cmd.parseOptions(argsStr.split(' ')); + + (cmd as any)._storeOptionsAsProperties = currentOpts; + (cmd as any)._optionValues = currentStore; + + return result; + }; +} diff --git a/packages/cli/src/modules/migrate/commands/packageExports.ts b/packages/cli/src/modules/migrate/commands/packageExports.ts index 4eb741ce4d..0d02782509 100644 --- a/packages/cli/src/modules/migrate/commands/packageExports.ts +++ b/packages/cli/src/modules/migrate/commands/packageExports.ts @@ -14,21 +14,8 @@ * limitations under the License. */ -import { - fixPackageExports, - readFixablePackages, - writeFixedPackages, -} from '../../maintenance/commands/repo/fix'; - export async function command() { console.log( - 'The `migrate package-exports` command is deprecated, use `repo fix` instead.', + 'The `migrate package-exports` command has been removed, use `repo fix` instead.', ); - const packages = await readFixablePackages(); - - for (const pkg of packages) { - fixPackageExports(pkg); - } - - await writeFixedPackages(packages); }