From 94a885a2ef0546de5b061bed0fd44504d26c9200 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 27 Feb 2026 23:25:27 +0100 Subject: [PATCH 01/45] Add cli-plugin package role Signed-off-by: Patrik Oldsberg --- .changeset/add-cli-plugin-role.md | 5 +++++ .changeset/cli-support-cli-plugin-role.md | 5 +++++ packages/cli-node/report.api.md | 1 + packages/cli-node/src/roles/PackageRoles.ts | 5 +++++ packages/cli-node/src/roles/types.ts | 1 + packages/cli/config/eslint-factory.js | 1 + packages/cli/config/jest.js | 1 + .../src/modules/build/lib/typeDistProject.test.ts | 1 + .../src/modules/maintenance/commands/repo/fix.ts | 14 ++++++++++++-- .../src/modules/migrate/commands/packageScripts.ts | 2 +- 10 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 .changeset/add-cli-plugin-role.md create mode 100644 .changeset/cli-support-cli-plugin-role.md diff --git a/.changeset/add-cli-plugin-role.md b/.changeset/add-cli-plugin-role.md new file mode 100644 index 0000000000..b31c631762 --- /dev/null +++ b/.changeset/add-cli-plugin-role.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli-node': patch +--- + +Added a new `cli-plugin` package role for packages that provide CLI plugin extensions. diff --git a/.changeset/cli-support-cli-plugin-role.md b/.changeset/cli-support-cli-plugin-role.md new file mode 100644 index 0000000000..d56c30db78 --- /dev/null +++ b/.changeset/cli-support-cli-plugin-role.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Added support for the new `cli-plugin` package role in the build system, ESLint configuration, Jest configuration, and maintenance commands. diff --git a/packages/cli-node/report.api.md b/packages/cli-node/report.api.md index 9d4887ca59..05d1545ae4 100644 --- a/packages/cli-node/report.api.md +++ b/packages/cli-node/report.api.md @@ -187,6 +187,7 @@ export type PackageRole = | 'frontend' | 'backend' | 'cli' + | 'cli-plugin' | 'web-library' | 'node-library' | 'common-library' diff --git a/packages/cli-node/src/roles/PackageRoles.ts b/packages/cli-node/src/roles/PackageRoles.ts index 70b62e2479..b0ee82af84 100644 --- a/packages/cli-node/src/roles/PackageRoles.ts +++ b/packages/cli-node/src/roles/PackageRoles.ts @@ -33,6 +33,11 @@ const packageRoleInfos: PackageRoleInfo[] = [ platform: 'node', output: ['cjs'], }, + { + role: 'cli-plugin', + platform: 'node', + output: ['types', 'cjs'], + }, { role: 'web-library', platform: 'web', diff --git a/packages/cli-node/src/roles/types.ts b/packages/cli-node/src/roles/types.ts index d6eff04541..29e5fbb5d6 100644 --- a/packages/cli-node/src/roles/types.ts +++ b/packages/cli-node/src/roles/types.ts @@ -23,6 +23,7 @@ export type PackageRole = | 'frontend' | 'backend' | 'cli' + | 'cli-plugin' | 'web-library' | 'node-library' | 'common-library' diff --git a/packages/cli/config/eslint-factory.js b/packages/cli/config/eslint-factory.js index dbb40537ab..db547f9b15 100644 --- a/packages/cli/config/eslint-factory.js +++ b/packages/cli/config/eslint-factory.js @@ -269,6 +269,7 @@ function createConfigForRole(dir, role, extraConfig = {}) { }); case 'cli': + case 'cli-plugin': case 'node-library': case 'backend': case 'backend-plugin': diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js index c670f0fe8b..07f92002ae 100644 --- a/packages/cli/config/jest.js +++ b/packages/cli/config/jest.js @@ -38,6 +38,7 @@ const FRONTEND_ROLES = [ const NODE_ROLES = [ 'backend', 'cli', + 'cli-plugin', 'node-library', 'backend-plugin', 'backend-plugin-module', diff --git a/packages/cli/src/modules/build/lib/typeDistProject.test.ts b/packages/cli/src/modules/build/lib/typeDistProject.test.ts index 6eef53816b..c773c505be 100644 --- a/packages/cli/src/modules/build/lib/typeDistProject.test.ts +++ b/packages/cli/src/modules/build/lib/typeDistProject.test.ts @@ -33,6 +33,7 @@ describe('typeDistProject', () => { frontend: false, backend: false, cli: false, + 'cli-plugin': false, 'common-library': false, }; diff --git a/packages/cli/src/modules/maintenance/commands/repo/fix.ts b/packages/cli/src/modules/maintenance/commands/repo/fix.ts index dc2e554121..324b4c6a3f 100644 --- a/packages/cli/src/modules/maintenance/commands/repo/fix.ts +++ b/packages/cli/src/modules/maintenance/commands/repo/fix.ts @@ -294,7 +294,12 @@ export function fixPluginId(pkg: FixablePackage) { return; } - if (role === 'backend' || role === 'frontend' || role === 'cli') { + if ( + role === 'backend' || + role === 'frontend' || + role === 'cli' || + role === 'cli-plugin' + ) { return; } @@ -376,7 +381,12 @@ export function fixPluginPackages( return; } - if (role === 'backend' || role === 'frontend' || role === 'cli') { + if ( + role === 'backend' || + role === 'frontend' || + role === 'cli' || + role === 'cli-plugin' + ) { return; } diff --git a/packages/cli/src/modules/migrate/commands/packageScripts.ts b/packages/cli/src/modules/migrate/commands/packageScripts.ts index 901cd8fc82..f9b4b56591 100644 --- a/packages/cli/src/modules/migrate/commands/packageScripts.ts +++ b/packages/cli/src/modules/migrate/commands/packageScripts.ts @@ -22,7 +22,7 @@ import type { CommandContext } from '../../../wiring/types'; const configArgPattern = /--config[=\s][^\s$]+/; -const noStartRoles: PackageRole[] = ['cli', 'common-library']; +const noStartRoles: PackageRole[] = ['cli', 'cli-plugin', 'common-library']; export default async ({ args, info }: CommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); From 0be3eab18b6375b3b458c539bdd5b2d7ce23d187 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 10 Mar 2026 22:06:36 +0100 Subject: [PATCH 02/45] cli: initial cli-plugin-api Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/cli-use-cli-plugin-api.md | 5 + .changeset/create-cli-plugin-api.md | 5 + packages/cli-plugin-api/catalog-info.yaml | 10 ++ packages/cli-plugin-api/package.json | 40 ++++++++ packages/cli-plugin-api/report.api.md | 96 +++++++++++++++++++ .../cli-plugin-api/src/createCliPlugin.ts | 36 +++++++ .../src/describeParentCallSite.ts | 54 +++++++++++ packages/cli-plugin-api/src/errors.ts | 72 ++++++++++++++ .../src/index.ts} | 18 +++- packages/cli-plugin-api/src/internals.ts | 40 ++++++++ packages/cli-plugin-api/src/lazy.ts | 59 ++++++++++++ packages/cli-plugin-api/src/types.ts | 91 ++++++++++++++++++ packages/cli/package.json | 1 + packages/cli/src/modules/build/index.ts | 2 +- .../cli/src/modules/config/commands/docs.ts | 2 +- .../cli/src/modules/config/commands/print.ts | 2 +- .../cli/src/modules/config/commands/schema.ts | 2 +- .../src/modules/config/commands/validate.ts | 2 +- packages/cli/src/modules/config/index.ts | 2 +- .../src/modules/create-github-app/index.ts | 2 +- .../cli/src/modules/info/commands/info.ts | 2 +- packages/cli/src/modules/info/index.ts | 2 +- packages/cli/src/modules/lint/index.ts | 2 +- packages/cli/src/modules/maintenance/index.ts | 2 +- packages/cli/src/modules/migrate/index.ts | 2 +- packages/cli/src/modules/new/index.ts | 2 +- packages/cli/src/modules/test/index.ts | 2 +- .../modules/translations/commands/export.ts | 2 +- .../modules/translations/commands/import.ts | 2 +- .../cli/src/modules/translations/index.ts | 2 +- packages/cli/src/wiring/CliInitializer.ts | 13 ++- packages/cli/src/wiring/errors.ts | 47 +-------- packages/cli/src/wiring/factory.ts | 16 +--- packages/cli/src/wiring/lazy.ts | 32 +------ packages/cli/src/wiring/types.ts | 57 ++--------- yarn.lock | 11 +++ 36 files changed, 569 insertions(+), 168 deletions(-) create mode 100644 .changeset/cli-use-cli-plugin-api.md create mode 100644 .changeset/create-cli-plugin-api.md create mode 100644 packages/cli-plugin-api/catalog-info.yaml create mode 100644 packages/cli-plugin-api/package.json create mode 100644 packages/cli-plugin-api/report.api.md create mode 100644 packages/cli-plugin-api/src/createCliPlugin.ts create mode 100644 packages/cli-plugin-api/src/describeParentCallSite.ts create mode 100644 packages/cli-plugin-api/src/errors.ts rename packages/{cli/src/wiring/describeParentCallSite.ts => cli-plugin-api/src/index.ts} (58%) create mode 100644 packages/cli-plugin-api/src/internals.ts create mode 100644 packages/cli-plugin-api/src/lazy.ts create mode 100644 packages/cli-plugin-api/src/types.ts diff --git a/.changeset/cli-use-cli-plugin-api.md b/.changeset/cli-use-cli-plugin-api.md new file mode 100644 index 0000000000..c16d0e2c06 --- /dev/null +++ b/.changeset/cli-use-cli-plugin-api.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Migrated CLI plugin modules to import from the new `@backstage/cli-plugin-api` package. diff --git a/.changeset/create-cli-plugin-api.md b/.changeset/create-cli-plugin-api.md new file mode 100644 index 0000000000..0b758c76dd --- /dev/null +++ b/.changeset/create-cli-plugin-api.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli-plugin-api': minor +--- + +Added a new `@backstage/cli-plugin-api` package that provides the public API for building Backstage CLI plugins. This includes `createCliPlugin`, `lazy`, `ExitCodeError`, `exitWithError`, and associated types. diff --git a/packages/cli-plugin-api/catalog-info.yaml b/packages/cli-plugin-api/catalog-info.yaml new file mode 100644 index 0000000000..3a0aca14b9 --- /dev/null +++ b/packages/cli-plugin-api/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-plugin-api + title: '@backstage/cli-plugin-api' + description: API for building Backstage CLI plugins +spec: + lifecycle: experimental + type: backstage-cli-plugin + owner: tooling-maintainers diff --git a/packages/cli-plugin-api/package.json b/packages/cli-plugin-api/package.json new file mode 100644 index 0000000000..d7fb328943 --- /dev/null +++ b/packages/cli-plugin-api/package.json @@ -0,0 +1,40 @@ +{ + "name": "@backstage/cli-plugin-api", + "version": "0.1.0", + "description": "API for building Backstage CLI plugins", + "backstage": { + "role": "cli-plugin" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-plugin-api" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/errors": "workspace:^", + "chalk": "^4.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } +} diff --git a/packages/cli-plugin-api/report.api.md b/packages/cli-plugin-api/report.api.md new file mode 100644 index 0000000000..7d5b9ed63c --- /dev/null +++ b/packages/cli-plugin-api/report.api.md @@ -0,0 +1,96 @@ +## API Report File for "@backstage/cli-plugin-api" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CustomErrorBase } from '@backstage/errors'; + +// @public +export type ActionExports = { + [KName in keyof TModule as TModule[KName] extends ( + ...args: any[] + ) => Promise + ? KName + : never]: TModule[KName]; +}; + +// @public +export interface BackstageCommand { + // (undocumented) + deprecated?: boolean; + // (undocumented) + description: string; + // (undocumented) + execute: + | CommandExecuteFn + | { + loader: () => Promise<{ + default: CommandExecuteFn; + }>; + }; + // (undocumented) + path: string[]; +} + +// @public +export type CliFeature = CliPlugin; + +// @public +export interface CliPlugin { + // (undocumented) + readonly $$type: '@backstage/CliPlugin'; + // (undocumented) + readonly pluginId: string; +} + +// @public +export interface CommandContext { + // (undocumented) + args: string[]; + // (undocumented) + info: { + usage: string; + description: string; + }; +} + +// @public +export type CommandExecuteFn = (context: CommandContext) => Promise; + +// @public +export function createCliPlugin(options: { + pluginId: string; + init: (registry: { + addCommand: (command: BackstageCommand) => void; + }) => Promise; +}): CliPlugin; + +// @public +export class ExitCodeError extends CustomErrorBase { + constructor(code: number, command?: string); + // (undocumented) + readonly code: number; +} + +// @public +export function exitWithError(error: unknown): never; + +// @public +export function initializeCliPlugin( + plugin: CliPlugin, + registry: { + addCommand: (command: BackstageCommand) => void; + }, +): Promise; + +// @public +export function isCliPlugin(value: unknown): value is CliPlugin; + +// @public +export function lazy( + moduleLoader: () => Promise, + exportName: keyof ActionExports, +): (...args: any[]) => Promise; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-plugin-api/src/createCliPlugin.ts b/packages/cli-plugin-api/src/createCliPlugin.ts new file mode 100644 index 0000000000..df2d3e02fd --- /dev/null +++ b/packages/cli-plugin-api/src/createCliPlugin.ts @@ -0,0 +1,36 @@ +/* + * 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 { describeParentCallSite } from './describeParentCallSite'; +import { BackstageCommand, CliPlugin, OpaqueCliPlugin } from './types'; + +/** + * Creates a new CLI plugin that provides commands to the Backstage CLI. + * + * @public + */ +export function createCliPlugin(options: { + pluginId: string; + init: (registry: { + addCommand: (command: BackstageCommand) => void; + }) => Promise; +}): CliPlugin { + return OpaqueCliPlugin.createInstance('v1', { + pluginId: options.pluginId, + init: options.init, + description: `created at '${describeParentCallSite()}'`, + }); +} diff --git a/packages/cli-plugin-api/src/describeParentCallSite.ts b/packages/cli-plugin-api/src/describeParentCallSite.ts new file mode 100644 index 0000000000..641365bde8 --- /dev/null +++ b/packages/cli-plugin-api/src/describeParentCallSite.ts @@ -0,0 +1,54 @@ +/* + * Copyright 2023 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. + */ + +const MESSAGE_MARKER = 'eHgtF5hmbrXyiEvo'; + +/** + * Internal helper that describes the location of the parent caller. + * @internal + */ +export function describeParentCallSite( + ErrorConstructor: { new (message: string): Error } = Error, +): string { + const { stack } = new ErrorConstructor(MESSAGE_MARKER); + if (!stack) { + return ''; + } + + const startIndex = stack.includes(MESSAGE_MARKER) + ? stack.indexOf('\n') + 1 + : 0; + const secondEntryStart = + stack.indexOf('\n', stack.indexOf('\n', startIndex) + 1) + 1; + const secondEntryEnd = stack.indexOf('\n', secondEntryStart); + + const line = stack.substring(secondEntryStart, secondEntryEnd).trim(); + if (!line) { + return 'unknown'; + } + + // Chrome + if (line.includes('(')) { + return line.substring(line.indexOf('(') + 1, line.indexOf(')')); + } + + // Safari & Firefox + if (line.includes('@')) { + return line.substring(line.indexOf('@') + 1); + } + + return line; +} diff --git a/packages/cli-plugin-api/src/errors.ts b/packages/cli-plugin-api/src/errors.ts new file mode 100644 index 0000000000..5334345608 --- /dev/null +++ b/packages/cli-plugin-api/src/errors.ts @@ -0,0 +1,72 @@ +/* + * Copyright 2020 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 { CustomErrorBase, isError, stringifyError } from '@backstage/errors'; +import chalk from 'chalk'; + +/** + * An error that indicates a child process exited with a specific code. + * + * @public + */ +export class ExitCodeError extends CustomErrorBase { + readonly code: number; + + constructor(code: number, command?: string) { + super( + command + ? `Command '${command}' exited with code ${code}` + : `Child exited with code ${code}`, + ); + this.code = code; + } +} + +function exit(message: string, code: number = 1): never { + process.stderr.write(`\n${chalk.red(message)}\n\n`); + process.exit(code); +} + +/** + * Exits the process with an appropriate error code based on the error type. + * + * @public + */ +export function exitWithError(error: unknown): never { + if (!isError(error)) { + process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`); + process.exit(1); + } + + switch (error.name) { + case 'InputError': + return exit(error.message, 74 /* input/output error */); + case 'NotFoundError': + return exit(error.message, 127 /* command not found */); + case 'NotImplementedError': + return exit(error.message, 64 /* command line usage error */); + case 'AuthenticationError': + case 'NotAllowedError': + return exit(error.message, 77 /* permission denied */); + case 'ExitCodeError': + return exit( + error.message, + 'code' in error && typeof error.code === 'number' ? error.code : 1, + ); + default: + return exit(stringifyError(error), 1); + } +} diff --git a/packages/cli/src/wiring/describeParentCallSite.ts b/packages/cli-plugin-api/src/index.ts similarity index 58% rename from packages/cli/src/wiring/describeParentCallSite.ts rename to packages/cli-plugin-api/src/index.ts index 35603e33b0..be990b7357 100644 --- a/packages/cli/src/wiring/describeParentCallSite.ts +++ b/packages/cli-plugin-api/src/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Backstage Authors + * 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. @@ -14,7 +14,15 @@ * limitations under the License. */ -// Single re-export to avoid doing this import in multiple places, but still -// avoid duplicate declarations because this one is a bit tricky. -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -export { describeParentCallSite } from '../../../frontend-plugin-api/src/routing/describeParentCallSite'; +export { createCliPlugin } from './createCliPlugin'; +export { lazy } from './lazy'; +export type { ActionExports } from './lazy'; +export { ExitCodeError, exitWithError } from './errors'; +export type { + BackstageCommand, + CommandContext, + CommandExecuteFn, + CliPlugin, + CliFeature, +} from './types'; +export { isCliPlugin, initializeCliPlugin } from './internals'; diff --git a/packages/cli-plugin-api/src/internals.ts b/packages/cli-plugin-api/src/internals.ts new file mode 100644 index 0000000000..99c1c4d1f8 --- /dev/null +++ b/packages/cli-plugin-api/src/internals.ts @@ -0,0 +1,40 @@ +/* + * 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 { BackstageCommand, CliPlugin, OpaqueCliPlugin } from './types'; + +/** + * Checks whether a value is a {@link CliPlugin}. + * + * @public + */ +export function isCliPlugin(value: unknown): value is CliPlugin { + return OpaqueCliPlugin.isType(value); +} + +/** + * Initializes a CLI plugin by calling its init function with the provided + * command registry. + * + * @public + */ +export async function initializeCliPlugin( + plugin: CliPlugin, + registry: { addCommand: (command: BackstageCommand) => void }, +): Promise { + const internal = OpaqueCliPlugin.toInternal(plugin); + await internal.init(registry); +} diff --git a/packages/cli-plugin-api/src/lazy.ts b/packages/cli-plugin-api/src/lazy.ts new file mode 100644 index 0000000000..30b8568fb1 --- /dev/null +++ b/packages/cli-plugin-api/src/lazy.ts @@ -0,0 +1,59 @@ +/* + * 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 { assertError } from '@backstage/errors'; +import { exitWithError } from './errors'; + +/** + * A mapped type that extracts keys of a module whose values are async action functions. + * + * @public + */ +export type ActionExports = { + [KName in keyof TModule as TModule[KName] extends ( + ...args: any[] + ) => Promise + ? KName + : never]: TModule[KName]; +}; + +/** + * Wraps an action function so that it always exits and handles errors. + * + * @public + */ +export function lazy( + moduleLoader: () => Promise, + exportName: keyof ActionExports, +): (...args: any[]) => Promise { + return async (...args: any[]) => { + try { + const mod = await moduleLoader(); + const actualModule = ( + mod as unknown as { default: ActionExports } + ).default; + const actionFunc = actualModule[exportName] as ( + ...args: any[] + ) => Promise; + await actionFunc(...args); + + process.exit(0); + } catch (error) { + assertError(error); + exitWithError(error); + } + }; +} diff --git a/packages/cli-plugin-api/src/types.ts b/packages/cli-plugin-api/src/types.ts new file mode 100644 index 0000000000..1736537580 --- /dev/null +++ b/packages/cli-plugin-api/src/types.ts @@ -0,0 +1,91 @@ +/* + * 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 { OpaqueType } from '@internal/opaque'; + +/** + * The context provided to a CLI command when it is executed. + * + * @public + */ +export interface CommandContext { + args: string[]; + info: { + /** + * The usage string of the current command, for example: "backstage-cli repo test" + */ + usage: string; + /** + * The description provided for the command + */ + description: string; + }; +} + +/** + * A function that executes a CLI command. + * + * @public + */ +export type CommandExecuteFn = (context: CommandContext) => Promise; + +/** + * A command definition for a Backstage CLI plugin. + * + * @public + */ +export interface BackstageCommand { + path: string[]; + description: string; + deprecated?: boolean; + experimental?: boolean; + execute: + | CommandExecuteFn + | { + loader: () => Promise<{ default: CommandExecuteFn }>; + }; +} + +/** + * A CLI feature, currently always a CLI plugin. + * + * @public + */ +export type CliFeature = CliPlugin; + +/** + * A Backstage CLI plugin. + * + * @public + */ +export interface CliPlugin { + readonly pluginId: string; + readonly $$type: '@backstage/CliPlugin'; +} + +/** @internal */ +export const OpaqueCliPlugin = OpaqueType.create<{ + public: CliPlugin; + versions: { + readonly version: 'v1'; + readonly description: string; + init: (registry: { + addCommand: (command: BackstageCommand) => void; + }) => Promise; + }; +}>({ + type: '@backstage/CliPlugin', + versions: ['v1'], +}); diff --git a/packages/cli/package.json b/packages/cli/package.json index 8e03c60d0f..d309e0453c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -50,6 +50,7 @@ "@backstage/catalog-model": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^", + "@backstage/cli-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/packages/cli/src/modules/build/index.ts b/packages/cli/src/modules/build/index.ts index 139c591af2..2ccf1e3b6e 100644 --- a/packages/cli/src/modules/build/index.ts +++ b/packages/cli/src/modules/build/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; export const buildPlugin = createCliPlugin({ pluginId: 'build', diff --git a/packages/cli/src/modules/config/commands/docs.ts b/packages/cli/src/modules/config/commands/docs.ts index 84d2f384e1..8015947a57 100644 --- a/packages/cli/src/modules/config/commands/docs.ts +++ b/packages/cli/src/modules/config/commands/docs.ts @@ -21,7 +21,7 @@ import { JSONSchema7 as JSONSchema } from 'json-schema'; import openBrowser from 'react-dev-utils/openBrowser'; import chalk from 'chalk'; import { loadCliConfig } from '../lib/config'; -import type { CommandContext } from '../../../wiring/types'; +import type { CommandContext } from '@backstage/cli-plugin-api'; const DOCS_URL = 'https://config.backstage.io'; diff --git a/packages/cli/src/modules/config/commands/print.ts b/packages/cli/src/modules/config/commands/print.ts index 33f7245604..db681f4619 100644 --- a/packages/cli/src/modules/config/commands/print.ts +++ b/packages/cli/src/modules/config/commands/print.ts @@ -19,7 +19,7 @@ import { stringify as stringifyYaml } from 'yaml'; import { AppConfig, ConfigReader } from '@backstage/config'; import { loadCliConfig } from '../lib/config'; import { ConfigSchema, ConfigVisibility } from '@backstage/config-loader'; -import type { CommandContext } from '../../../wiring/types'; +import type { CommandContext } from '@backstage/cli-plugin-api'; export default async ({ args, info }: CommandContext) => { const { diff --git a/packages/cli/src/modules/config/commands/schema.ts b/packages/cli/src/modules/config/commands/schema.ts index 13f651534c..1635caf7e6 100644 --- a/packages/cli/src/modules/config/commands/schema.ts +++ b/packages/cli/src/modules/config/commands/schema.ts @@ -20,7 +20,7 @@ import { stringify as stringifyYaml } from 'yaml'; import { loadCliConfig } from '../lib/config'; import { JsonObject } from '@backstage/types'; import { mergeConfigSchemas } from '@backstage/config-loader'; -import type { CommandContext } from '../../../wiring/types'; +import type { CommandContext } from '@backstage/cli-plugin-api'; export default async ({ args, info }: CommandContext) => { const { diff --git a/packages/cli/src/modules/config/commands/validate.ts b/packages/cli/src/modules/config/commands/validate.ts index f6cf9cc662..302c0b6480 100644 --- a/packages/cli/src/modules/config/commands/validate.ts +++ b/packages/cli/src/modules/config/commands/validate.ts @@ -16,7 +16,7 @@ import { cli } from 'cleye'; import { loadCliConfig } from '../lib/config'; -import type { CommandContext } from '../../../wiring/types'; +import type { CommandContext } from '@backstage/cli-plugin-api'; export default async ({ args, info }: CommandContext) => { const { diff --git a/packages/cli/src/modules/config/index.ts b/packages/cli/src/modules/config/index.ts index 0d90037f18..c8fb6bca7e 100644 --- a/packages/cli/src/modules/config/index.ts +++ b/packages/cli/src/modules/config/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; export const configOption = [ '--config ', diff --git a/packages/cli/src/modules/create-github-app/index.ts b/packages/cli/src/modules/create-github-app/index.ts index 9dad46577e..ea6cbf55be 100644 --- a/packages/cli/src/modules/create-github-app/index.ts +++ b/packages/cli/src/modules/create-github-app/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; export default createCliPlugin({ pluginId: 'new', diff --git a/packages/cli/src/modules/info/commands/info.ts b/packages/cli/src/modules/info/commands/info.ts index ab26714fca..0170c4204a 100644 --- a/packages/cli/src/modules/info/commands/info.ts +++ b/packages/cli/src/modules/info/commands/info.ts @@ -25,7 +25,7 @@ import { } from '@backstage/cli-node'; import { minimatch } from 'minimatch'; import fs from 'fs-extra'; -import type { CommandContext } from '../../../wiring/types'; +import type { CommandContext } from '@backstage/cli-plugin-api'; /** * Attempts to read package.json from node_modules for a given package name. diff --git a/packages/cli/src/modules/info/index.ts b/packages/cli/src/modules/info/index.ts index 8e1fe9cbff..11ff207281 100644 --- a/packages/cli/src/modules/info/index.ts +++ b/packages/cli/src/modules/info/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; export default createCliPlugin({ pluginId: 'info', diff --git a/packages/cli/src/modules/lint/index.ts b/packages/cli/src/modules/lint/index.ts index 8e02b7653f..d825740b9f 100644 --- a/packages/cli/src/modules/lint/index.ts +++ b/packages/cli/src/modules/lint/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; export default createCliPlugin({ pluginId: 'lint', diff --git a/packages/cli/src/modules/maintenance/index.ts b/packages/cli/src/modules/maintenance/index.ts index a6597559f8..4356c4654f 100644 --- a/packages/cli/src/modules/maintenance/index.ts +++ b/packages/cli/src/modules/maintenance/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; export default createCliPlugin({ pluginId: 'maintenance', diff --git a/packages/cli/src/modules/migrate/index.ts b/packages/cli/src/modules/migrate/index.ts index c731479a51..87c0543e90 100644 --- a/packages/cli/src/modules/migrate/index.ts +++ b/packages/cli/src/modules/migrate/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; export default createCliPlugin({ pluginId: 'migrate', diff --git a/packages/cli/src/modules/new/index.ts b/packages/cli/src/modules/new/index.ts index 5b2a6562ea..2d30fb45bc 100644 --- a/packages/cli/src/modules/new/index.ts +++ b/packages/cli/src/modules/new/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; import { NotImplementedError } from '@backstage/errors'; export default createCliPlugin({ diff --git a/packages/cli/src/modules/test/index.ts b/packages/cli/src/modules/test/index.ts index 627648332b..f991d23ce2 100644 --- a/packages/cli/src/modules/test/index.ts +++ b/packages/cli/src/modules/test/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; export default createCliPlugin({ pluginId: 'test', diff --git a/packages/cli/src/modules/translations/commands/export.ts b/packages/cli/src/modules/translations/commands/export.ts index b6471f10f4..146e9ce121 100644 --- a/packages/cli/src/modules/translations/commands/export.ts +++ b/packages/cli/src/modules/translations/commands/export.ts @@ -33,7 +33,7 @@ import { formatMessagePath, validatePattern, } from '../lib/messageFilePath'; -import type { CommandContext } from '../../../wiring/types'; +import type { CommandContext } from '@backstage/cli-plugin-api'; export default async ({ args, info }: CommandContext) => { const { diff --git a/packages/cli/src/modules/translations/commands/import.ts b/packages/cli/src/modules/translations/commands/import.ts index 155724dd8c..2739dbac41 100644 --- a/packages/cli/src/modules/translations/commands/import.ts +++ b/packages/cli/src/modules/translations/commands/import.ts @@ -28,7 +28,7 @@ import { createMessagePathParser, formatMessagePath, } from '../lib/messageFilePath'; -import type { CommandContext } from '../../../wiring/types'; +import type { CommandContext } from '@backstage/cli-plugin-api'; interface ManifestRefEntry { package: string; diff --git a/packages/cli/src/modules/translations/index.ts b/packages/cli/src/modules/translations/index.ts index 43263831d5..9a001bab23 100644 --- a/packages/cli/src/modules/translations/index.ts +++ b/packages/cli/src/modules/translations/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliPlugin } from '@backstage/cli-plugin-api'; export default createCliPlugin({ pluginId: 'translations', diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index d9af1e8a4d..b44dba862f 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -15,12 +15,16 @@ */ import { CommandGraph } from './CommandGraph'; -import { BackstageCommand, CliFeature, OpaqueCliPlugin } from './types'; +import { + isCliPlugin, + initializeCliPlugin, + exitWithError, +} from '@backstage/cli-plugin-api'; +import type { BackstageCommand, CliFeature } from '@backstage/cli-plugin-api'; import { CommandRegistry } from './CommandRegistry'; import { Command } from 'commander'; import { version } from './version'; import chalk from 'chalk'; -import { exitWithError } from './errors'; import { ForwardedError } from '@backstage/errors'; import { isPromise } from 'node:util/types'; @@ -53,9 +57,8 @@ export class CliInitializer { } async #register(feature: CliFeature) { - if (OpaqueCliPlugin.isType(feature)) { - const internal = OpaqueCliPlugin.toInternal(feature); - await internal.init(this.commandRegistry); + if (isCliPlugin(feature)) { + await initializeCliPlugin(feature, this.commandRegistry); } else { throw new Error(`Unsupported feature type: ${(feature as any).$$type}`); } diff --git a/packages/cli/src/wiring/errors.ts b/packages/cli/src/wiring/errors.ts index aee6d3f575..b684f5c64a 100644 --- a/packages/cli/src/wiring/errors.ts +++ b/packages/cli/src/wiring/errors.ts @@ -14,49 +14,4 @@ * limitations under the License. */ -import { CustomErrorBase, isError, stringifyError } from '@backstage/errors'; -import chalk from 'chalk'; - -export class ExitCodeError extends CustomErrorBase { - readonly code: number; - - constructor(code: number, command?: string) { - super( - command - ? `Command '${command}' exited with code ${code}` - : `Child exited with code ${code}`, - ); - this.code = code; - } -} - -function exit(message: string, code: number = 1): never { - process.stderr.write(`\n${chalk.red(message)}\n\n`); - process.exit(code); -} - -export function exitWithError(error: unknown): never { - if (!isError(error)) { - process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`); - process.exit(1); - } - - switch (error.name) { - case 'InputError': - return exit(error.message, 74 /* input/output error */); - case 'NotFoundError': - return exit(error.message, 127 /* command not found */); - case 'NotImplementedError': - return exit(error.message, 64 /* command line usage error */); - case 'AuthenticationError': - case 'NotAllowedError': - return exit(error.message, 77 /* permissino denied */); - case 'ExitCodeError': - return exit( - error.message, - 'code' in error && typeof error.code === 'number' ? error.code : 1, - ); - default: - return exit(stringifyError(error), 1); - } -} +export { ExitCodeError, exitWithError } from '@backstage/cli-plugin-api'; diff --git a/packages/cli/src/wiring/factory.ts b/packages/cli/src/wiring/factory.ts index 6374f37c14..19c68e805f 100644 --- a/packages/cli/src/wiring/factory.ts +++ b/packages/cli/src/wiring/factory.ts @@ -14,18 +14,4 @@ * limitations under the License. */ -import { describeParentCallSite } from './describeParentCallSite'; -import { BackstageCommand, CliPlugin, OpaqueCliPlugin } from './types'; - -export function createCliPlugin(options: { - pluginId: string; - init: (registry: { - addCommand: (command: BackstageCommand) => void; - }) => Promise; -}): CliPlugin { - return OpaqueCliPlugin.createInstance('v1', { - pluginId: options.pluginId, - init: options.init, - description: `created at '${describeParentCallSite()}'`, - }); -} +export { createCliPlugin } from '@backstage/cli-plugin-api'; diff --git a/packages/cli/src/wiring/lazy.ts b/packages/cli/src/wiring/lazy.ts index 64a4d43ef4..feda134d07 100644 --- a/packages/cli/src/wiring/lazy.ts +++ b/packages/cli/src/wiring/lazy.ts @@ -14,34 +14,4 @@ * limitations under the License. */ -import { assertError } from '@backstage/errors'; -import { exitWithError } from './errors'; - -type ActionFunc = (...args: any[]) => Promise; -type ActionExports = { - [KName in keyof TModule as TModule[KName] extends ActionFunc - ? KName - : never]: TModule[KName]; -}; - -// Wraps an action function so that it always exits and handles errors -export function lazy( - moduleLoader: () => Promise, - exportName: keyof ActionExports, -): (...args: any[]) => Promise { - return async (...args: any[]) => { - try { - const mod = await moduleLoader(); - const actualModule = ( - mod as unknown as { default: ActionExports } - ).default; - const actionFunc = actualModule[exportName] as ActionFunc; - await actionFunc(...args); - - process.exit(0); - } catch (error) { - assertError(error); - exitWithError(error); - } - }; -} +export { lazy } from '@backstage/cli-plugin-api'; diff --git a/packages/cli/src/wiring/types.ts b/packages/cli/src/wiring/types.ts index fa3d2341f0..0cf4f849a9 100644 --- a/packages/cli/src/wiring/types.ts +++ b/packages/cli/src/wiring/types.ts @@ -13,53 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { OpaqueType } from '@internal/opaque'; -export interface CommandContext { - args: string[]; - info: { - /** - * The usage string of the current command, for example: "backstage-cli repo test" - */ - usage: string; - /** - * The description provided for the command - */ - description: string; - }; -} - -export type CommandExecuteFn = (context: CommandContext) => Promise; - -export interface BackstageCommand { - path: string[]; - description: string; - deprecated?: boolean; - experimental?: boolean; - execute: - | CommandExecuteFn - | { - loader: () => Promise<{ default: CommandExecuteFn }>; - }; -} - -export type CliFeature = CliPlugin; - -export interface CliPlugin { - readonly pluginId: string; - readonly $$type: '@backstage/CliPlugin'; -} - -export const OpaqueCliPlugin = OpaqueType.create<{ - public: CliPlugin; - versions: { - readonly version: 'v1'; - readonly description: string; - init: (registry: { - addCommand: (command: BackstageCommand) => void; - }) => Promise; - }; -}>({ - type: '@backstage/CliPlugin', - versions: ['v1'], -}); +// Re-export types from the plugin API for internal use within the CLI package. +export type { + CommandContext, + CommandExecuteFn, + BackstageCommand, + CliFeature, + CliPlugin, +} from '@backstage/cli-plugin-api'; diff --git a/yarn.lock b/yarn.lock index 32b09cc5e3..6977b9161f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2822,6 +2822,16 @@ __metadata: languageName: unknown linkType: soft +"@backstage/cli-plugin-api@workspace:^, @backstage/cli-plugin-api@workspace:packages/cli-plugin-api": + version: 0.0.0-use.local + resolution: "@backstage/cli-plugin-api@workspace:packages/cli-plugin-api" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/errors": "workspace:^" + chalk: "npm:^4.0.0" + languageName: unknown + linkType: soft + "@backstage/cli@workspace:*, @backstage/cli@workspace:^, @backstage/cli@workspace:packages/cli": version: 0.0.0-use.local resolution: "@backstage/cli@workspace:packages/cli" @@ -2832,6 +2842,7 @@ __metadata: "@backstage/catalog-model": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" + "@backstage/cli-plugin-api": "workspace:^" "@backstage/config": "workspace:^" "@backstage/config-loader": "workspace:^" "@backstage/core-app-api": "workspace:^" From d6caf7f13bebd4d90028104446d7f97b62ed5078 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 11 Mar 2026 08:09:32 +0100 Subject: [PATCH 03/45] Slim cli-plugin-api to only export createCliPlugin Move error handling and lazy utilities back to @backstage/cli since they are host-only concerns. The cli-plugin-api internals subpath provides isCliPlugin and initializeCliPlugin for the CLI host. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/cli-use-cli-plugin-api.md | 2 +- .changeset/create-cli-plugin-api.md | 2 +- packages/cli-plugin-api/.eslintrc.js | 1 + packages/cli-plugin-api/package.json | 22 ++++-- .../cli-plugin-api/report-internals.api.md | 60 ++++++++++++++++ packages/cli-plugin-api/report.api.md | 40 +---------- packages/cli-plugin-api/src/errors.ts | 72 ------------------- packages/cli-plugin-api/src/index.ts | 4 -- packages/cli-plugin-api/src/internals.ts | 7 ++ packages/cli-plugin-api/src/lazy.ts | 59 --------------- .../cli/src/modules/config/commands/docs.ts | 2 +- .../cli/src/modules/config/commands/print.ts | 2 +- .../cli/src/modules/config/commands/schema.ts | 2 +- .../src/modules/config/commands/validate.ts | 2 +- .../cli/src/modules/info/commands/info.ts | 2 +- .../modules/translations/commands/export.ts | 2 +- .../modules/translations/commands/import.ts | 2 +- packages/cli/src/wiring/CliInitializer.ts | 4 +- packages/cli/src/wiring/errors.ts | 47 +++++++++++- packages/cli/src/wiring/lazy.ts | 32 ++++++++- packages/cli/src/wiring/types.ts | 1 - yarn.lock | 1 - 22 files changed, 175 insertions(+), 193 deletions(-) create mode 100644 packages/cli-plugin-api/.eslintrc.js create mode 100644 packages/cli-plugin-api/report-internals.api.md delete mode 100644 packages/cli-plugin-api/src/errors.ts delete mode 100644 packages/cli-plugin-api/src/lazy.ts diff --git a/.changeset/cli-use-cli-plugin-api.md b/.changeset/cli-use-cli-plugin-api.md index c16d0e2c06..b55858ba62 100644 --- a/.changeset/cli-use-cli-plugin-api.md +++ b/.changeset/cli-use-cli-plugin-api.md @@ -2,4 +2,4 @@ '@backstage/cli': patch --- -Migrated CLI plugin modules to import from the new `@backstage/cli-plugin-api` package. +Migrated CLI plugin modules to use `createCliPlugin` from the new `@backstage/cli-plugin-api` package. diff --git a/.changeset/create-cli-plugin-api.md b/.changeset/create-cli-plugin-api.md index 0b758c76dd..d740fe7897 100644 --- a/.changeset/create-cli-plugin-api.md +++ b/.changeset/create-cli-plugin-api.md @@ -2,4 +2,4 @@ '@backstage/cli-plugin-api': minor --- -Added a new `@backstage/cli-plugin-api` package that provides the public API for building Backstage CLI plugins. This includes `createCliPlugin`, `lazy`, `ExitCodeError`, `exitWithError`, and associated types. +Added a new `@backstage/cli-plugin-api` package that provides the `createCliPlugin` API for building Backstage CLI plugins. diff --git a/packages/cli-plugin-api/.eslintrc.js b/packages/cli-plugin-api/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-plugin-api/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-plugin-api/package.json b/packages/cli-plugin-api/package.json index d7fb328943..051b764c6a 100644 --- a/packages/cli-plugin-api/package.json +++ b/packages/cli-plugin-api/package.json @@ -6,9 +6,7 @@ "role": "cli-plugin" }, "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" }, "homepage": "https://backstage.io", "repository": { @@ -17,8 +15,23 @@ "directory": "packages/cli-plugin-api" }, "license": "Apache-2.0", + "exports": { + ".": "./src/index.ts", + "./internals": "./src/internals.ts", + "./package.json": "./package.json" + }, "main": "src/index.ts", "types": "src/index.ts", + "typesVersions": { + "*": { + "internals": [ + "src/internals.ts" + ], + "package.json": [ + "package.json" + ] + } + }, "files": [ "dist" ], @@ -31,8 +44,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/errors": "workspace:^", - "chalk": "^4.0.0" + "@backstage/errors": "workspace:^" }, "devDependencies": { "@backstage/cli": "workspace:^" diff --git a/packages/cli-plugin-api/report-internals.api.md b/packages/cli-plugin-api/report-internals.api.md new file mode 100644 index 0000000000..b5721e6972 --- /dev/null +++ b/packages/cli-plugin-api/report-internals.api.md @@ -0,0 +1,60 @@ +## API Report File for "@backstage/cli-plugin-api" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +// @public +export interface BackstageCommand { + // (undocumented) + deprecated?: boolean; + // (undocumented) + description: string; + // (undocumented) + execute: + | CommandExecuteFn + | { + loader: () => Promise<{ + default: CommandExecuteFn; + }>; + }; + // (undocumented) + experimental?: boolean; + // (undocumented) + path: string[]; +} + +// @public +export interface CliPlugin { + // (undocumented) + readonly $$type: '@backstage/CliPlugin'; + // (undocumented) + readonly pluginId: string; +} + +// @public +export interface CommandContext { + // (undocumented) + args: string[]; + // (undocumented) + info: { + usage: string; + description: string; + }; +} + +// @public +export type CommandExecuteFn = (context: CommandContext) => Promise; + +// @public +export function initializeCliPlugin( + plugin: CliPlugin, + registry: { + addCommand: (command: BackstageCommand) => void; + }, +): Promise; + +// @public +export function isCliPlugin(value: unknown): value is CliPlugin; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-plugin-api/report.api.md b/packages/cli-plugin-api/report.api.md index 7d5b9ed63c..3562bb20e6 100644 --- a/packages/cli-plugin-api/report.api.md +++ b/packages/cli-plugin-api/report.api.md @@ -3,17 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { CustomErrorBase } from '@backstage/errors'; - -// @public -export type ActionExports = { - [KName in keyof TModule as TModule[KName] extends ( - ...args: any[] - ) => Promise - ? KName - : never]: TModule[KName]; -}; - // @public export interface BackstageCommand { // (undocumented) @@ -29,6 +18,8 @@ export interface BackstageCommand { }>; }; // (undocumented) + experimental?: boolean; + // (undocumented) path: string[]; } @@ -65,32 +56,5 @@ export function createCliPlugin(options: { }) => Promise; }): CliPlugin; -// @public -export class ExitCodeError extends CustomErrorBase { - constructor(code: number, command?: string); - // (undocumented) - readonly code: number; -} - -// @public -export function exitWithError(error: unknown): never; - -// @public -export function initializeCliPlugin( - plugin: CliPlugin, - registry: { - addCommand: (command: BackstageCommand) => void; - }, -): Promise; - -// @public -export function isCliPlugin(value: unknown): value is CliPlugin; - -// @public -export function lazy( - moduleLoader: () => Promise, - exportName: keyof ActionExports, -): (...args: any[]) => Promise; - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/cli-plugin-api/src/errors.ts b/packages/cli-plugin-api/src/errors.ts deleted file mode 100644 index 5334345608..0000000000 --- a/packages/cli-plugin-api/src/errors.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2020 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 { CustomErrorBase, isError, stringifyError } from '@backstage/errors'; -import chalk from 'chalk'; - -/** - * An error that indicates a child process exited with a specific code. - * - * @public - */ -export class ExitCodeError extends CustomErrorBase { - readonly code: number; - - constructor(code: number, command?: string) { - super( - command - ? `Command '${command}' exited with code ${code}` - : `Child exited with code ${code}`, - ); - this.code = code; - } -} - -function exit(message: string, code: number = 1): never { - process.stderr.write(`\n${chalk.red(message)}\n\n`); - process.exit(code); -} - -/** - * Exits the process with an appropriate error code based on the error type. - * - * @public - */ -export function exitWithError(error: unknown): never { - if (!isError(error)) { - process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`); - process.exit(1); - } - - switch (error.name) { - case 'InputError': - return exit(error.message, 74 /* input/output error */); - case 'NotFoundError': - return exit(error.message, 127 /* command not found */); - case 'NotImplementedError': - return exit(error.message, 64 /* command line usage error */); - case 'AuthenticationError': - case 'NotAllowedError': - return exit(error.message, 77 /* permission denied */); - case 'ExitCodeError': - return exit( - error.message, - 'code' in error && typeof error.code === 'number' ? error.code : 1, - ); - default: - return exit(stringifyError(error), 1); - } -} diff --git a/packages/cli-plugin-api/src/index.ts b/packages/cli-plugin-api/src/index.ts index be990b7357..15082804ee 100644 --- a/packages/cli-plugin-api/src/index.ts +++ b/packages/cli-plugin-api/src/index.ts @@ -15,9 +15,6 @@ */ export { createCliPlugin } from './createCliPlugin'; -export { lazy } from './lazy'; -export type { ActionExports } from './lazy'; -export { ExitCodeError, exitWithError } from './errors'; export type { BackstageCommand, CommandContext, @@ -25,4 +22,3 @@ export type { CliPlugin, CliFeature, } from './types'; -export { isCliPlugin, initializeCliPlugin } from './internals'; diff --git a/packages/cli-plugin-api/src/internals.ts b/packages/cli-plugin-api/src/internals.ts index 99c1c4d1f8..f851decbad 100644 --- a/packages/cli-plugin-api/src/internals.ts +++ b/packages/cli-plugin-api/src/internals.ts @@ -16,6 +16,13 @@ import { BackstageCommand, CliPlugin, OpaqueCliPlugin } from './types'; +export type { + BackstageCommand, + CliPlugin, + CommandContext, + CommandExecuteFn, +} from './types'; + /** * Checks whether a value is a {@link CliPlugin}. * diff --git a/packages/cli-plugin-api/src/lazy.ts b/packages/cli-plugin-api/src/lazy.ts deleted file mode 100644 index 30b8568fb1..0000000000 --- a/packages/cli-plugin-api/src/lazy.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 { assertError } from '@backstage/errors'; -import { exitWithError } from './errors'; - -/** - * A mapped type that extracts keys of a module whose values are async action functions. - * - * @public - */ -export type ActionExports = { - [KName in keyof TModule as TModule[KName] extends ( - ...args: any[] - ) => Promise - ? KName - : never]: TModule[KName]; -}; - -/** - * Wraps an action function so that it always exits and handles errors. - * - * @public - */ -export function lazy( - moduleLoader: () => Promise, - exportName: keyof ActionExports, -): (...args: any[]) => Promise { - return async (...args: any[]) => { - try { - const mod = await moduleLoader(); - const actualModule = ( - mod as unknown as { default: ActionExports } - ).default; - const actionFunc = actualModule[exportName] as ( - ...args: any[] - ) => Promise; - await actionFunc(...args); - - process.exit(0); - } catch (error) { - assertError(error); - exitWithError(error); - } - }; -} diff --git a/packages/cli/src/modules/config/commands/docs.ts b/packages/cli/src/modules/config/commands/docs.ts index 8015947a57..84d2f384e1 100644 --- a/packages/cli/src/modules/config/commands/docs.ts +++ b/packages/cli/src/modules/config/commands/docs.ts @@ -21,7 +21,7 @@ import { JSONSchema7 as JSONSchema } from 'json-schema'; import openBrowser from 'react-dev-utils/openBrowser'; import chalk from 'chalk'; import { loadCliConfig } from '../lib/config'; -import type { CommandContext } from '@backstage/cli-plugin-api'; +import type { CommandContext } from '../../../wiring/types'; const DOCS_URL = 'https://config.backstage.io'; diff --git a/packages/cli/src/modules/config/commands/print.ts b/packages/cli/src/modules/config/commands/print.ts index db681f4619..33f7245604 100644 --- a/packages/cli/src/modules/config/commands/print.ts +++ b/packages/cli/src/modules/config/commands/print.ts @@ -19,7 +19,7 @@ import { stringify as stringifyYaml } from 'yaml'; import { AppConfig, ConfigReader } from '@backstage/config'; import { loadCliConfig } from '../lib/config'; import { ConfigSchema, ConfigVisibility } from '@backstage/config-loader'; -import type { CommandContext } from '@backstage/cli-plugin-api'; +import type { CommandContext } from '../../../wiring/types'; export default async ({ args, info }: CommandContext) => { const { diff --git a/packages/cli/src/modules/config/commands/schema.ts b/packages/cli/src/modules/config/commands/schema.ts index 1635caf7e6..13f651534c 100644 --- a/packages/cli/src/modules/config/commands/schema.ts +++ b/packages/cli/src/modules/config/commands/schema.ts @@ -20,7 +20,7 @@ import { stringify as stringifyYaml } from 'yaml'; import { loadCliConfig } from '../lib/config'; import { JsonObject } from '@backstage/types'; import { mergeConfigSchemas } from '@backstage/config-loader'; -import type { CommandContext } from '@backstage/cli-plugin-api'; +import type { CommandContext } from '../../../wiring/types'; export default async ({ args, info }: CommandContext) => { const { diff --git a/packages/cli/src/modules/config/commands/validate.ts b/packages/cli/src/modules/config/commands/validate.ts index 302c0b6480..f6cf9cc662 100644 --- a/packages/cli/src/modules/config/commands/validate.ts +++ b/packages/cli/src/modules/config/commands/validate.ts @@ -16,7 +16,7 @@ import { cli } from 'cleye'; import { loadCliConfig } from '../lib/config'; -import type { CommandContext } from '@backstage/cli-plugin-api'; +import type { CommandContext } from '../../../wiring/types'; export default async ({ args, info }: CommandContext) => { const { diff --git a/packages/cli/src/modules/info/commands/info.ts b/packages/cli/src/modules/info/commands/info.ts index 0170c4204a..ab26714fca 100644 --- a/packages/cli/src/modules/info/commands/info.ts +++ b/packages/cli/src/modules/info/commands/info.ts @@ -25,7 +25,7 @@ import { } from '@backstage/cli-node'; import { minimatch } from 'minimatch'; import fs from 'fs-extra'; -import type { CommandContext } from '@backstage/cli-plugin-api'; +import type { CommandContext } from '../../../wiring/types'; /** * Attempts to read package.json from node_modules for a given package name. diff --git a/packages/cli/src/modules/translations/commands/export.ts b/packages/cli/src/modules/translations/commands/export.ts index 146e9ce121..b6471f10f4 100644 --- a/packages/cli/src/modules/translations/commands/export.ts +++ b/packages/cli/src/modules/translations/commands/export.ts @@ -33,7 +33,7 @@ import { formatMessagePath, validatePattern, } from '../lib/messageFilePath'; -import type { CommandContext } from '@backstage/cli-plugin-api'; +import type { CommandContext } from '../../../wiring/types'; export default async ({ args, info }: CommandContext) => { const { diff --git a/packages/cli/src/modules/translations/commands/import.ts b/packages/cli/src/modules/translations/commands/import.ts index 2739dbac41..155724dd8c 100644 --- a/packages/cli/src/modules/translations/commands/import.ts +++ b/packages/cli/src/modules/translations/commands/import.ts @@ -28,7 +28,7 @@ import { createMessagePathParser, formatMessagePath, } from '../lib/messageFilePath'; -import type { CommandContext } from '@backstage/cli-plugin-api'; +import type { CommandContext } from '../../../wiring/types'; interface ManifestRefEntry { package: string; diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index b44dba862f..72269f3274 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -18,13 +18,13 @@ import { CommandGraph } from './CommandGraph'; import { isCliPlugin, initializeCliPlugin, - exitWithError, -} from '@backstage/cli-plugin-api'; +} from '@backstage/cli-plugin-api/internals'; import type { BackstageCommand, CliFeature } from '@backstage/cli-plugin-api'; import { CommandRegistry } from './CommandRegistry'; import { Command } from 'commander'; import { version } from './version'; import chalk from 'chalk'; +import { exitWithError } from './errors'; import { ForwardedError } from '@backstage/errors'; import { isPromise } from 'node:util/types'; diff --git a/packages/cli/src/wiring/errors.ts b/packages/cli/src/wiring/errors.ts index b684f5c64a..aee6d3f575 100644 --- a/packages/cli/src/wiring/errors.ts +++ b/packages/cli/src/wiring/errors.ts @@ -14,4 +14,49 @@ * limitations under the License. */ -export { ExitCodeError, exitWithError } from '@backstage/cli-plugin-api'; +import { CustomErrorBase, isError, stringifyError } from '@backstage/errors'; +import chalk from 'chalk'; + +export class ExitCodeError extends CustomErrorBase { + readonly code: number; + + constructor(code: number, command?: string) { + super( + command + ? `Command '${command}' exited with code ${code}` + : `Child exited with code ${code}`, + ); + this.code = code; + } +} + +function exit(message: string, code: number = 1): never { + process.stderr.write(`\n${chalk.red(message)}\n\n`); + process.exit(code); +} + +export function exitWithError(error: unknown): never { + if (!isError(error)) { + process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`); + process.exit(1); + } + + switch (error.name) { + case 'InputError': + return exit(error.message, 74 /* input/output error */); + case 'NotFoundError': + return exit(error.message, 127 /* command not found */); + case 'NotImplementedError': + return exit(error.message, 64 /* command line usage error */); + case 'AuthenticationError': + case 'NotAllowedError': + return exit(error.message, 77 /* permissino denied */); + case 'ExitCodeError': + return exit( + error.message, + 'code' in error && typeof error.code === 'number' ? error.code : 1, + ); + default: + return exit(stringifyError(error), 1); + } +} diff --git a/packages/cli/src/wiring/lazy.ts b/packages/cli/src/wiring/lazy.ts index feda134d07..64a4d43ef4 100644 --- a/packages/cli/src/wiring/lazy.ts +++ b/packages/cli/src/wiring/lazy.ts @@ -14,4 +14,34 @@ * limitations under the License. */ -export { lazy } from '@backstage/cli-plugin-api'; +import { assertError } from '@backstage/errors'; +import { exitWithError } from './errors'; + +type ActionFunc = (...args: any[]) => Promise; +type ActionExports = { + [KName in keyof TModule as TModule[KName] extends ActionFunc + ? KName + : never]: TModule[KName]; +}; + +// Wraps an action function so that it always exits and handles errors +export function lazy( + moduleLoader: () => Promise, + exportName: keyof ActionExports, +): (...args: any[]) => Promise { + return async (...args: any[]) => { + try { + const mod = await moduleLoader(); + const actualModule = ( + mod as unknown as { default: ActionExports } + ).default; + const actionFunc = actualModule[exportName] as ActionFunc; + await actionFunc(...args); + + process.exit(0); + } catch (error) { + assertError(error); + exitWithError(error); + } + }; +} diff --git a/packages/cli/src/wiring/types.ts b/packages/cli/src/wiring/types.ts index 0cf4f849a9..4fd58a5c73 100644 --- a/packages/cli/src/wiring/types.ts +++ b/packages/cli/src/wiring/types.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -// Re-export types from the plugin API for internal use within the CLI package. export type { CommandContext, CommandExecuteFn, diff --git a/yarn.lock b/yarn.lock index 6977b9161f..2173b5a314 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2828,7 +2828,6 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@backstage/errors": "workspace:^" - chalk: "npm:^4.0.0" languageName: unknown linkType: soft From 2e5f189cfa91f71eeed66dbfeb21cef7f693cdd7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 11 Mar 2026 08:18:55 +0100 Subject: [PATCH 04/45] Add @internal/cli package for opaque CLI types Move OpaqueCliPlugin to a new @internal/cli inline package, following the same pattern as @internal/frontend. Both cli-plugin-api and cli import it directly, and it gets bundled into their dists at build time. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-internal/.eslintrc.js | 1 + packages/cli-internal/catalog-info.yaml | 9 +++ packages/cli-internal/package.json | 30 ++++++++++ .../cli-internal/src/InternalCliPlugin.ts | 32 ++++++++++ packages/cli-internal/src/index.ts | 17 ++++++ packages/cli-plugin-api/package.json | 19 +----- .../cli-plugin-api/report-internals.api.md | 60 ------------------- .../cli-plugin-api/src/createCliPlugin.ts | 3 +- packages/cli-plugin-api/src/internals.ts | 47 --------------- packages/cli-plugin-api/src/types.ts | 16 ----- packages/cli/src/wiring/CliInitializer.ts | 10 ++-- yarn.lock | 9 +++ 12 files changed, 107 insertions(+), 146 deletions(-) create mode 100644 packages/cli-internal/.eslintrc.js create mode 100644 packages/cli-internal/catalog-info.yaml create mode 100644 packages/cli-internal/package.json create mode 100644 packages/cli-internal/src/InternalCliPlugin.ts create mode 100644 packages/cli-internal/src/index.ts delete mode 100644 packages/cli-plugin-api/report-internals.api.md delete mode 100644 packages/cli-plugin-api/src/internals.ts diff --git a/packages/cli-internal/.eslintrc.js b/packages/cli-internal/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-internal/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-internal/catalog-info.yaml b/packages/cli-internal/catalog-info.yaml new file mode 100644 index 0000000000..2f2a1c837a --- /dev/null +++ b/packages/cli-internal/catalog-info.yaml @@ -0,0 +1,9 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: internal-cli + title: '@internal/cli' +spec: + lifecycle: experimental + type: backstage-node-library + owner: tooling-maintainers diff --git a/packages/cli-internal/package.json b/packages/cli-internal/package.json new file mode 100644 index 0000000000..80c68c74d3 --- /dev/null +++ b/packages/cli-internal/package.json @@ -0,0 +1,30 @@ +{ + "name": "@internal/cli", + "version": "0.0.1", + "backstage": { + "role": "node-library", + "inline": true + }, + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-internal" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "lint": "backstage-cli package lint", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-plugin-api": "workspace:^" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } +} diff --git a/packages/cli-internal/src/InternalCliPlugin.ts b/packages/cli-internal/src/InternalCliPlugin.ts new file mode 100644 index 0000000000..62bf5013c8 --- /dev/null +++ b/packages/cli-internal/src/InternalCliPlugin.ts @@ -0,0 +1,32 @@ +/* + * 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 { BackstageCommand, CliPlugin } from '@backstage/cli-plugin-api'; +import { OpaqueType } from '@internal/opaque'; + +export const OpaqueCliPlugin = OpaqueType.create<{ + public: CliPlugin; + versions: { + readonly version: 'v1'; + readonly description: string; + init: (registry: { + addCommand: (command: BackstageCommand) => void; + }) => Promise; + }; +}>({ + type: '@backstage/CliPlugin', + versions: ['v1'], +}); diff --git a/packages/cli-internal/src/index.ts b/packages/cli-internal/src/index.ts new file mode 100644 index 0000000000..a1dc8ad24c --- /dev/null +++ b/packages/cli-internal/src/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export { OpaqueCliPlugin } from './InternalCliPlugin'; diff --git a/packages/cli-plugin-api/package.json b/packages/cli-plugin-api/package.json index 051b764c6a..4d256f3c96 100644 --- a/packages/cli-plugin-api/package.json +++ b/packages/cli-plugin-api/package.json @@ -6,7 +6,9 @@ "role": "cli-plugin" }, "publishConfig": { - "access": "public" + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" }, "homepage": "https://backstage.io", "repository": { @@ -15,23 +17,8 @@ "directory": "packages/cli-plugin-api" }, "license": "Apache-2.0", - "exports": { - ".": "./src/index.ts", - "./internals": "./src/internals.ts", - "./package.json": "./package.json" - }, "main": "src/index.ts", "types": "src/index.ts", - "typesVersions": { - "*": { - "internals": [ - "src/internals.ts" - ], - "package.json": [ - "package.json" - ] - } - }, "files": [ "dist" ], diff --git a/packages/cli-plugin-api/report-internals.api.md b/packages/cli-plugin-api/report-internals.api.md deleted file mode 100644 index b5721e6972..0000000000 --- a/packages/cli-plugin-api/report-internals.api.md +++ /dev/null @@ -1,60 +0,0 @@ -## API Report File for "@backstage/cli-plugin-api" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -// @public -export interface BackstageCommand { - // (undocumented) - deprecated?: boolean; - // (undocumented) - description: string; - // (undocumented) - execute: - | CommandExecuteFn - | { - loader: () => Promise<{ - default: CommandExecuteFn; - }>; - }; - // (undocumented) - experimental?: boolean; - // (undocumented) - path: string[]; -} - -// @public -export interface CliPlugin { - // (undocumented) - readonly $$type: '@backstage/CliPlugin'; - // (undocumented) - readonly pluginId: string; -} - -// @public -export interface CommandContext { - // (undocumented) - args: string[]; - // (undocumented) - info: { - usage: string; - description: string; - }; -} - -// @public -export type CommandExecuteFn = (context: CommandContext) => Promise; - -// @public -export function initializeCliPlugin( - plugin: CliPlugin, - registry: { - addCommand: (command: BackstageCommand) => void; - }, -): Promise; - -// @public -export function isCliPlugin(value: unknown): value is CliPlugin; - -// (No @packageDocumentation comment for this package) -``` diff --git a/packages/cli-plugin-api/src/createCliPlugin.ts b/packages/cli-plugin-api/src/createCliPlugin.ts index df2d3e02fd..7a8d299394 100644 --- a/packages/cli-plugin-api/src/createCliPlugin.ts +++ b/packages/cli-plugin-api/src/createCliPlugin.ts @@ -14,8 +14,9 @@ * limitations under the License. */ +import { OpaqueCliPlugin } from '@internal/cli'; import { describeParentCallSite } from './describeParentCallSite'; -import { BackstageCommand, CliPlugin, OpaqueCliPlugin } from './types'; +import { BackstageCommand, CliPlugin } from './types'; /** * Creates a new CLI plugin that provides commands to the Backstage CLI. diff --git a/packages/cli-plugin-api/src/internals.ts b/packages/cli-plugin-api/src/internals.ts deleted file mode 100644 index f851decbad..0000000000 --- a/packages/cli-plugin-api/src/internals.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 { BackstageCommand, CliPlugin, OpaqueCliPlugin } from './types'; - -export type { - BackstageCommand, - CliPlugin, - CommandContext, - CommandExecuteFn, -} from './types'; - -/** - * Checks whether a value is a {@link CliPlugin}. - * - * @public - */ -export function isCliPlugin(value: unknown): value is CliPlugin { - return OpaqueCliPlugin.isType(value); -} - -/** - * Initializes a CLI plugin by calling its init function with the provided - * command registry. - * - * @public - */ -export async function initializeCliPlugin( - plugin: CliPlugin, - registry: { addCommand: (command: BackstageCommand) => void }, -): Promise { - const internal = OpaqueCliPlugin.toInternal(plugin); - await internal.init(registry); -} diff --git a/packages/cli-plugin-api/src/types.ts b/packages/cli-plugin-api/src/types.ts index 1736537580..42d006ce5c 100644 --- a/packages/cli-plugin-api/src/types.ts +++ b/packages/cli-plugin-api/src/types.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { OpaqueType } from '@internal/opaque'; /** * The context provided to a CLI command when it is executed. @@ -74,18 +73,3 @@ export interface CliPlugin { readonly pluginId: string; readonly $$type: '@backstage/CliPlugin'; } - -/** @internal */ -export const OpaqueCliPlugin = OpaqueType.create<{ - public: CliPlugin; - versions: { - readonly version: 'v1'; - readonly description: string; - init: (registry: { - addCommand: (command: BackstageCommand) => void; - }) => Promise; - }; -}>({ - type: '@backstage/CliPlugin', - versions: ['v1'], -}); diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index 72269f3274..bd31930854 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -15,10 +15,7 @@ */ import { CommandGraph } from './CommandGraph'; -import { - isCliPlugin, - initializeCliPlugin, -} from '@backstage/cli-plugin-api/internals'; +import { OpaqueCliPlugin } from '@internal/cli'; import type { BackstageCommand, CliFeature } from '@backstage/cli-plugin-api'; import { CommandRegistry } from './CommandRegistry'; import { Command } from 'commander'; @@ -57,8 +54,9 @@ export class CliInitializer { } async #register(feature: CliFeature) { - if (isCliPlugin(feature)) { - await initializeCliPlugin(feature, this.commandRegistry); + if (OpaqueCliPlugin.isType(feature)) { + const internal = OpaqueCliPlugin.toInternal(feature); + await internal.init(this.commandRegistry); } else { throw new Error(`Unsupported feature type: ${(feature as any).$$type}`); } diff --git a/yarn.lock b/yarn.lock index 2173b5a314..2ef9ed9764 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9680,6 +9680,15 @@ __metadata: languageName: node linkType: hard +"@internal/cli@workspace:packages/cli-internal": + version: 0.0.0-use.local + resolution: "@internal/cli@workspace:packages/cli-internal" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-plugin-api": "workspace:^" + languageName: unknown + linkType: soft + "@internal/frontend@workspace:packages/frontend-internal": version: 0.0.0-use.local resolution: "@internal/frontend@workspace:packages/frontend-internal" From 7e6ad01a21a9a369459c5c147a83e3b007955196 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 11 Mar 2026 08:38:58 +0100 Subject: [PATCH 05/45] Refine cli-plugin-api: use packageJson, inline types, rename context fields Replace pluginId with packageJson input for createCliPlugin, remove CommandExecuteFn type alias by inlining it, and rename CommandContext.info.description to info.name. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../cli-internal/src/InternalCliPlugin.ts | 6 +-- packages/cli-plugin-api/report.api.md | 13 ++--- .../cli-plugin-api/src/createCliPlugin.ts | 13 +++-- .../src/describeParentCallSite.ts | 54 ------------------- packages/cli-plugin-api/src/index.ts | 1 - packages/cli-plugin-api/src/types.ts | 18 +++---- packages/cli/src/modules/auth/index.ts | 3 +- packages/cli/src/modules/build/index.ts | 3 +- packages/cli/src/modules/config/index.ts | 3 +- .../src/modules/create-github-app/index.ts | 3 +- packages/cli/src/modules/info/index.ts | 3 +- packages/cli/src/modules/lint/index.ts | 3 +- packages/cli/src/modules/maintenance/index.ts | 3 +- .../migrate/commands/versions/bump.test.ts | 2 +- .../migrate/commands/versions/migrate.test.ts | 6 +-- packages/cli/src/modules/migrate/index.ts | 3 +- .../cli/src/modules/new/commands/new.test.ts | 2 +- packages/cli/src/modules/new/index.ts | 3 +- packages/cli/src/modules/test/index.ts | 3 +- .../cli/src/modules/translations/index.ts | 3 +- .../cli/src/wiring/CliInitializer.test.ts | 16 +++--- packages/cli/src/wiring/CliInitializer.ts | 6 ++- packages/cli/src/wiring/types.ts | 1 - 23 files changed, 60 insertions(+), 111 deletions(-) delete mode 100644 packages/cli-plugin-api/src/describeParentCallSite.ts diff --git a/packages/cli-internal/src/InternalCliPlugin.ts b/packages/cli-internal/src/InternalCliPlugin.ts index 62bf5013c8..426f3d23e6 100644 --- a/packages/cli-internal/src/InternalCliPlugin.ts +++ b/packages/cli-internal/src/InternalCliPlugin.ts @@ -21,10 +21,8 @@ export const OpaqueCliPlugin = OpaqueType.create<{ public: CliPlugin; versions: { readonly version: 'v1'; - readonly description: string; - init: (registry: { - addCommand: (command: BackstageCommand) => void; - }) => Promise; + readonly packageName: string; + readonly commands: Promise>; }; }>({ type: '@backstage/CliPlugin', diff --git a/packages/cli-plugin-api/report.api.md b/packages/cli-plugin-api/report.api.md index 3562bb20e6..d72169495f 100644 --- a/packages/cli-plugin-api/report.api.md +++ b/packages/cli-plugin-api/report.api.md @@ -11,10 +11,10 @@ export interface BackstageCommand { description: string; // (undocumented) execute: - | CommandExecuteFn + | ((context: CommandContext) => Promise) | { loader: () => Promise<{ - default: CommandExecuteFn; + default: (context: CommandContext) => Promise; }>; }; // (undocumented) @@ -30,8 +30,6 @@ export type CliFeature = CliPlugin; export interface CliPlugin { // (undocumented) readonly $$type: '@backstage/CliPlugin'; - // (undocumented) - readonly pluginId: string; } // @public @@ -45,12 +43,11 @@ export interface CommandContext { }; } -// @public -export type CommandExecuteFn = (context: CommandContext) => Promise; - // @public export function createCliPlugin(options: { - pluginId: string; + packageJson: { + name: string; + }; init: (registry: { addCommand: (command: BackstageCommand) => void; }) => Promise; diff --git a/packages/cli-plugin-api/src/createCliPlugin.ts b/packages/cli-plugin-api/src/createCliPlugin.ts index 7a8d299394..04a26665a6 100644 --- a/packages/cli-plugin-api/src/createCliPlugin.ts +++ b/packages/cli-plugin-api/src/createCliPlugin.ts @@ -15,7 +15,6 @@ */ import { OpaqueCliPlugin } from '@internal/cli'; -import { describeParentCallSite } from './describeParentCallSite'; import { BackstageCommand, CliPlugin } from './types'; /** @@ -24,14 +23,18 @@ import { BackstageCommand, CliPlugin } from './types'; * @public */ export function createCliPlugin(options: { - pluginId: string; + packageJson: { name: string }; init: (registry: { addCommand: (command: BackstageCommand) => void; }) => Promise; }): CliPlugin { + const commands: BackstageCommand[] = []; + const commandsPromise = options + .init({ addCommand: command => commands.push(command) }) + .then(() => commands); + return OpaqueCliPlugin.createInstance('v1', { - pluginId: options.pluginId, - init: options.init, - description: `created at '${describeParentCallSite()}'`, + packageName: options.packageJson.name, + commands: commandsPromise, }); } diff --git a/packages/cli-plugin-api/src/describeParentCallSite.ts b/packages/cli-plugin-api/src/describeParentCallSite.ts deleted file mode 100644 index 641365bde8..0000000000 --- a/packages/cli-plugin-api/src/describeParentCallSite.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2023 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. - */ - -const MESSAGE_MARKER = 'eHgtF5hmbrXyiEvo'; - -/** - * Internal helper that describes the location of the parent caller. - * @internal - */ -export function describeParentCallSite( - ErrorConstructor: { new (message: string): Error } = Error, -): string { - const { stack } = new ErrorConstructor(MESSAGE_MARKER); - if (!stack) { - return ''; - } - - const startIndex = stack.includes(MESSAGE_MARKER) - ? stack.indexOf('\n') + 1 - : 0; - const secondEntryStart = - stack.indexOf('\n', stack.indexOf('\n', startIndex) + 1) + 1; - const secondEntryEnd = stack.indexOf('\n', secondEntryStart); - - const line = stack.substring(secondEntryStart, secondEntryEnd).trim(); - if (!line) { - return 'unknown'; - } - - // Chrome - if (line.includes('(')) { - return line.substring(line.indexOf('(') + 1, line.indexOf(')')); - } - - // Safari & Firefox - if (line.includes('@')) { - return line.substring(line.indexOf('@') + 1); - } - - return line; -} diff --git a/packages/cli-plugin-api/src/index.ts b/packages/cli-plugin-api/src/index.ts index 15082804ee..988600280c 100644 --- a/packages/cli-plugin-api/src/index.ts +++ b/packages/cli-plugin-api/src/index.ts @@ -18,7 +18,6 @@ export { createCliPlugin } from './createCliPlugin'; export type { BackstageCommand, CommandContext, - CommandExecuteFn, CliPlugin, CliFeature, } from './types'; diff --git a/packages/cli-plugin-api/src/types.ts b/packages/cli-plugin-api/src/types.ts index 42d006ce5c..3bdf026490 100644 --- a/packages/cli-plugin-api/src/types.ts +++ b/packages/cli-plugin-api/src/types.ts @@ -27,19 +27,12 @@ export interface CommandContext { */ usage: string; /** - * The description provided for the command + * The name of the command, for example: "repo test" */ - description: string; + name: string; }; } -/** - * A function that executes a CLI command. - * - * @public - */ -export type CommandExecuteFn = (context: CommandContext) => Promise; - /** * A command definition for a Backstage CLI plugin. * @@ -51,9 +44,11 @@ export interface BackstageCommand { deprecated?: boolean; experimental?: boolean; execute: - | CommandExecuteFn + | ((context: CommandContext) => Promise) | { - loader: () => Promise<{ default: CommandExecuteFn }>; + loader: () => Promise<{ + default: (context: CommandContext) => Promise; + }>; }; } @@ -70,6 +65,5 @@ export type CliFeature = CliPlugin; * @public */ export interface CliPlugin { - readonly pluginId: string; readonly $$type: '@backstage/CliPlugin'; } diff --git a/packages/cli/src/modules/auth/index.ts b/packages/cli/src/modules/auth/index.ts index d5766219b2..6ce849a9b9 100644 --- a/packages/cli/src/modules/auth/index.ts +++ b/packages/cli/src/modules/auth/index.ts @@ -15,9 +15,10 @@ */ import { createCliPlugin } from '../../wiring/factory'; +import packageJson from '../../../package.json'; export default createCliPlugin({ - pluginId: 'auth', + packageJson, init: async reg => { reg.addCommand({ path: ['auth', 'login'], diff --git a/packages/cli/src/modules/build/index.ts b/packages/cli/src/modules/build/index.ts index 2ccf1e3b6e..1c8d2217ed 100644 --- a/packages/cli/src/modules/build/index.ts +++ b/packages/cli/src/modules/build/index.ts @@ -15,9 +15,10 @@ */ import { createCliPlugin } from '@backstage/cli-plugin-api'; +import packageJson from '../../../package.json'; export const buildPlugin = createCliPlugin({ - pluginId: 'build', + packageJson, init: async reg => { reg.addCommand({ path: ['package', 'build'], diff --git a/packages/cli/src/modules/config/index.ts b/packages/cli/src/modules/config/index.ts index c8fb6bca7e..3c59f96948 100644 --- a/packages/cli/src/modules/config/index.ts +++ b/packages/cli/src/modules/config/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { createCliPlugin } from '@backstage/cli-plugin-api'; +import packageJson from '../../../package.json'; export const configOption = [ '--config ', @@ -23,7 +24,7 @@ export const configOption = [ ] as const; export default createCliPlugin({ - pluginId: 'config', + packageJson, init: async reg => { reg.addCommand({ path: ['config:docs'], diff --git a/packages/cli/src/modules/create-github-app/index.ts b/packages/cli/src/modules/create-github-app/index.ts index ea6cbf55be..69fe5869d4 100644 --- a/packages/cli/src/modules/create-github-app/index.ts +++ b/packages/cli/src/modules/create-github-app/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ import { createCliPlugin } from '@backstage/cli-plugin-api'; +import packageJson from '../../../package.json'; export default createCliPlugin({ - pluginId: 'new', + packageJson, init: async reg => { reg.addCommand({ path: ['create-github-app'], diff --git a/packages/cli/src/modules/info/index.ts b/packages/cli/src/modules/info/index.ts index 11ff207281..df8a848f11 100644 --- a/packages/cli/src/modules/info/index.ts +++ b/packages/cli/src/modules/info/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ import { createCliPlugin } from '@backstage/cli-plugin-api'; +import packageJson from '../../../package.json'; export default createCliPlugin({ - pluginId: 'info', + packageJson, init: async reg => { reg.addCommand({ path: ['info'], diff --git a/packages/cli/src/modules/lint/index.ts b/packages/cli/src/modules/lint/index.ts index d825740b9f..51e5b981a4 100644 --- a/packages/cli/src/modules/lint/index.ts +++ b/packages/cli/src/modules/lint/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ import { createCliPlugin } from '@backstage/cli-plugin-api'; +import packageJson from '../../../package.json'; export default createCliPlugin({ - pluginId: 'lint', + packageJson, init: async reg => { reg.addCommand({ path: ['package', 'lint'], diff --git a/packages/cli/src/modules/maintenance/index.ts b/packages/cli/src/modules/maintenance/index.ts index 4356c4654f..142bd543f2 100644 --- a/packages/cli/src/modules/maintenance/index.ts +++ b/packages/cli/src/modules/maintenance/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ import { createCliPlugin } from '@backstage/cli-plugin-api'; +import packageJson from '../../../package.json'; export default createCliPlugin({ - pluginId: 'maintenance', + packageJson, init: async reg => { reg.addCommand({ path: ['repo', 'fix'], diff --git a/packages/cli/src/modules/migrate/commands/versions/bump.test.ts b/packages/cli/src/modules/migrate/commands/versions/bump.test.ts index f119a0bedb..c7694f5e09 100644 --- a/packages/cli/src/modules/migrate/commands/versions/bump.test.ts +++ b/packages/cli/src/modules/migrate/commands/versions/bump.test.ts @@ -125,7 +125,7 @@ const expectLogsToMatch = ( expect(receivedLogs.filter(Boolean).sort()).toEqual(expected.sort()); }; -const info = { usage: 'backstage-cli versions:bump', description: '' }; +const info = { usage: 'backstage-cli versions:bump', name: 'versions:bump' }; describe('bump', () => { const mockDir = createMockDirectory(); diff --git a/packages/cli/src/modules/migrate/commands/versions/migrate.test.ts b/packages/cli/src/modules/migrate/commands/versions/migrate.test.ts index fc50a5c491..606fa528b1 100644 --- a/packages/cli/src/modules/migrate/commands/versions/migrate.test.ts +++ b/packages/cli/src/modules/migrate/commands/versions/migrate.test.ts @@ -123,7 +123,7 @@ describe('versions:migrate', () => { }); const { warn, log: logs } = await withLogCollector(async () => { - await migrate({ args: [], info: { usage: 'test', description: 'test' } }); + await migrate({ args: [], info: { usage: 'test', name: 'test' } }); }); expectLogsToMatch(logs, [ @@ -229,7 +229,7 @@ describe('versions:migrate', () => { }); await withLogCollector(async () => { - await migrate({ args: [], info: { usage: 'test', description: 'test' } }); + await migrate({ args: [], info: { usage: 'test', name: 'test' } }); }); expect(runObj.run).toHaveBeenCalledTimes(1); @@ -311,7 +311,7 @@ describe('versions:migrate', () => { }); await withLogCollector(async () => { - await migrate({ args: [], info: { usage: 'test', description: 'test' } }); + await migrate({ args: [], info: { usage: 'test', name: 'test' } }); }); expect(runObj.run).toHaveBeenCalledTimes(1); diff --git a/packages/cli/src/modules/migrate/index.ts b/packages/cli/src/modules/migrate/index.ts index 87c0543e90..603712f8e2 100644 --- a/packages/cli/src/modules/migrate/index.ts +++ b/packages/cli/src/modules/migrate/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ import { createCliPlugin } from '@backstage/cli-plugin-api'; +import packageJson from '../../../package.json'; export default createCliPlugin({ - pluginId: 'migrate', + packageJson, init: async reg => { reg.addCommand({ path: ['versions:migrate'], diff --git a/packages/cli/src/modules/new/commands/new.test.ts b/packages/cli/src/modules/new/commands/new.test.ts index 0da42e7019..9a490e8f9a 100644 --- a/packages/cli/src/modules/new/commands/new.test.ts +++ b/packages/cli/src/modules/new/commands/new.test.ts @@ -41,7 +41,7 @@ describe.each([ } const context: CommandContext = { args, - info: { usage: 'backstage-cli new', description: 'test' }, + info: { usage: 'backstage-cli new', name: 'new' }, }; await newCommand(context); expect(createNewPackage).toHaveBeenCalledWith( diff --git a/packages/cli/src/modules/new/index.ts b/packages/cli/src/modules/new/index.ts index 2d30fb45bc..076a49f9be 100644 --- a/packages/cli/src/modules/new/index.ts +++ b/packages/cli/src/modules/new/index.ts @@ -15,9 +15,10 @@ */ import { createCliPlugin } from '@backstage/cli-plugin-api'; import { NotImplementedError } from '@backstage/errors'; +import packageJson from '../../../package.json'; export default createCliPlugin({ - pluginId: 'new', + packageJson, init: async reg => { reg.addCommand({ path: ['new'], diff --git a/packages/cli/src/modules/test/index.ts b/packages/cli/src/modules/test/index.ts index f991d23ce2..596572cb9a 100644 --- a/packages/cli/src/modules/test/index.ts +++ b/packages/cli/src/modules/test/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ import { createCliPlugin } from '@backstage/cli-plugin-api'; +import packageJson from '../../../package.json'; export default createCliPlugin({ - pluginId: 'test', + packageJson, init: async reg => { reg.addCommand({ path: ['repo', 'test'], diff --git a/packages/cli/src/modules/translations/index.ts b/packages/cli/src/modules/translations/index.ts index 9a001bab23..16c19d9345 100644 --- a/packages/cli/src/modules/translations/index.ts +++ b/packages/cli/src/modules/translations/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ import { createCliPlugin } from '@backstage/cli-plugin-api'; +import packageJson from '../../../package.json'; export default createCliPlugin({ - pluginId: 'translations', + packageJson, init: async reg => { reg.addCommand({ path: ['translations', 'export'], diff --git a/packages/cli/src/wiring/CliInitializer.test.ts b/packages/cli/src/wiring/CliInitializer.test.ts index 10de6d8e09..c5d304db91 100644 --- a/packages/cli/src/wiring/CliInitializer.test.ts +++ b/packages/cli/src/wiring/CliInitializer.test.ts @@ -29,7 +29,7 @@ describe('CliInitializer', () => { const initializer = new CliInitializer(); initializer.add( createCliPlugin({ - pluginId: 'test', + packageJson: { name: '@backstage/test' }, init: async reg => reg.addCommand({ path: ['test'], @@ -51,7 +51,7 @@ describe('CliInitializer', () => { const initializer = new CliInitializer(); initializer.add( createCliPlugin({ - pluginId: 'test', + packageJson: { name: '@backstage/test' }, init: async reg => reg.addCommand({ path: ['test'], @@ -73,7 +73,7 @@ describe('CliInitializer', () => { const initializer = new CliInitializer(); initializer.add( createCliPlugin({ - pluginId: 'test', + packageJson: { name: '@backstage/test' }, init: async reg => reg.addCommand({ path: ['test'], @@ -98,7 +98,7 @@ describe('CliInitializer', () => { const initializer = new CliInitializer(); initializer.add( createCliPlugin({ - pluginId: 'test', + packageJson: { name: '@backstage/test' }, init: async reg => { reg.addCommand({ path: ['visible'], @@ -125,7 +125,7 @@ describe('CliInitializer', () => { const initializer2 = new CliInitializer(); initializer2.add( createCliPlugin({ - pluginId: 'test', + packageJson: { name: '@backstage/test' }, init: async reg => { reg.addCommand({ path: ['visible'], @@ -153,7 +153,7 @@ describe('CliInitializer', () => { const initializer = new CliInitializer(); initializer.add( createCliPlugin({ - pluginId: 'test', + packageJson: { name: '@backstage/test' }, init: async reg => { reg.addCommand({ path: ['visible'], @@ -188,7 +188,7 @@ describe('CliInitializer', () => { const initializer = new CliInitializer(); initializer.add( createCliPlugin({ - pluginId: 'test', + packageJson: { name: '@backstage/test' }, init: async reg => { reg.addCommand({ path: ['group', 'alpha'], @@ -224,7 +224,7 @@ describe('CliInitializer', () => { const initializer = new CliInitializer(); initializer.add( createCliPlugin({ - pluginId: 'test', + packageJson: { name: '@backstage/test' }, init: async reg => reg.addCommand({ path: ['test', 'nested', 'command'], diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index bd31930854..2d1f94ce79 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -56,7 +56,9 @@ export class CliInitializer { async #register(feature: CliFeature) { if (OpaqueCliPlugin.isType(feature)) { const internal = OpaqueCliPlugin.toInternal(feature); - await internal.init(this.commandRegistry); + for (const command of await internal.commands) { + this.commandRegistry.addCommand(command); + } } else { throw new Error(`Unsupported feature type: ${(feature as any).$$type}`); } @@ -138,7 +140,7 @@ export class CliInitializer { args: [...positionalArgs, ...args.unknown], info: { usage: [programName, ...node.command.path].join(' '), - description: node.command.description, + name: node.command.path.join(' '), }, }; diff --git a/packages/cli/src/wiring/types.ts b/packages/cli/src/wiring/types.ts index 4fd58a5c73..b635e48ac0 100644 --- a/packages/cli/src/wiring/types.ts +++ b/packages/cli/src/wiring/types.ts @@ -16,7 +16,6 @@ export type { CommandContext, - CommandExecuteFn, BackstageCommand, CliFeature, CliPlugin, From 28a438a9f2b4e3c866b82373ad26ba2d65d42962 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 11 Mar 2026 13:29:31 +0100 Subject: [PATCH 06/45] Add documentation to cli-plugin-api and remove CliFeature type Add thorough TSDoc comments to createCliPlugin, BackstageCommand, CommandContext, and CliPlugin. Remove the CliFeature type alias in favor of using CliPlugin directly. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-plugin-api/report.api.md | 9 +-- .../cli-plugin-api/src/createCliPlugin.ts | 27 +++++++ packages/cli-plugin-api/src/index.ts | 7 +- packages/cli-plugin-api/src/types.ts | 71 ++++++++++++++++--- packages/cli/src/wiring/CliInitializer.ts | 12 ++-- packages/cli/src/wiring/types.ts | 1 - 6 files changed, 95 insertions(+), 32 deletions(-) diff --git a/packages/cli-plugin-api/report.api.md b/packages/cli-plugin-api/report.api.md index d72169495f..0821e01085 100644 --- a/packages/cli-plugin-api/report.api.md +++ b/packages/cli-plugin-api/report.api.md @@ -5,11 +5,8 @@ ```ts // @public export interface BackstageCommand { - // (undocumented) deprecated?: boolean; - // (undocumented) description: string; - // (undocumented) execute: | ((context: CommandContext) => Promise) | { @@ -17,9 +14,7 @@ export interface BackstageCommand { default: (context: CommandContext) => Promise; }>; }; - // (undocumented) experimental?: boolean; - // (undocumented) path: string[]; } @@ -34,12 +29,10 @@ export interface CliPlugin { // @public export interface CommandContext { - // (undocumented) args: string[]; - // (undocumented) info: { usage: string; - description: string; + name: string; }; } diff --git a/packages/cli-plugin-api/src/createCliPlugin.ts b/packages/cli-plugin-api/src/createCliPlugin.ts index 04a26665a6..17ddd8ebb9 100644 --- a/packages/cli-plugin-api/src/createCliPlugin.ts +++ b/packages/cli-plugin-api/src/createCliPlugin.ts @@ -20,11 +20,38 @@ import { BackstageCommand, CliPlugin } from './types'; /** * Creates a new CLI plugin that provides commands to the Backstage CLI. * + * The `init` callback is invoked immediately at creation time and is used + * to register commands via the provided registry. The commands are then + * made available to the CLI host once the returned promise resolves. + * + * @example + * ``` + * import { createCliPlugin } from '@backstage/cli-plugin-api'; + * import packageJson from '../package.json'; + * + * export default createCliPlugin({ + * packageJson, + * init: async reg => { + * reg.addCommand({ + * path: ['repo', 'test'], + * description: 'Run tests across the repository', + * execute: { loader: () => import('./commands/test') }, + * }); + * }, + * }); + * ``` + * * @public */ export function createCliPlugin(options: { + /** The `package.json` contents of the plugin package, used to identify the plugin. */ packageJson: { name: string }; + /** + * An initialization callback that registers commands with the CLI. + * Called immediately when the plugin is created. + */ init: (registry: { + /** Registers a new command with the CLI. */ addCommand: (command: BackstageCommand) => void; }) => Promise; }): CliPlugin { diff --git a/packages/cli-plugin-api/src/index.ts b/packages/cli-plugin-api/src/index.ts index 988600280c..723b0edd55 100644 --- a/packages/cli-plugin-api/src/index.ts +++ b/packages/cli-plugin-api/src/index.ts @@ -15,9 +15,4 @@ */ export { createCliPlugin } from './createCliPlugin'; -export type { - BackstageCommand, - CommandContext, - CliPlugin, - CliFeature, -} from './types'; +export type { BackstageCommand, CommandContext, CliPlugin } from './types'; diff --git a/packages/cli-plugin-api/src/types.ts b/packages/cli-plugin-api/src/types.ts index 3bdf026490..cdb6d886ee 100644 --- a/packages/cli-plugin-api/src/types.ts +++ b/packages/cli-plugin-api/src/types.ts @@ -15,19 +15,33 @@ */ /** - * The context provided to a CLI command when it is executed. + * The context provided to a CLI command at the time of execution. + * + * Contains the parsed arguments and metadata about the command being run. * * @public */ export interface CommandContext { + /** + * The remaining arguments passed to the command after the command path + * has been resolved. This includes both positional arguments and flags. + * + * For example, running `backstage-cli repo test --verbose src/` would + * result in `args` being `['--verbose', 'src/']`. + */ args: string[]; + /** + * Metadata about the command being executed. + */ info: { /** - * The usage string of the current command, for example: "backstage-cli repo test" + * The full usage string of the command including the program name, + * for example `"backstage-cli repo test"`. */ usage: string; /** - * The name of the command, for example: "repo test" + * The name of the command as defined by its path, + * for example `"repo test"`. */ name: string; }; @@ -36,13 +50,54 @@ export interface CommandContext { /** * A command definition for a Backstage CLI plugin. * + * Each command is identified by a `path` that determines its position in + * the command tree. For example, a path of `['repo', 'test']` registers + * the command as `backstage-cli repo test`. + * + * Commands can either provide an `execute` function directly, or use a + * `loader` for deferred loading of the implementation. The loader pattern + * is recommended for commands with heavy dependencies, as it avoids + * loading the implementation until the command is actually invoked. + * * @public */ export interface BackstageCommand { + /** + * The path segments that define the command's position in the CLI tree. + * For example, `['repo', 'test']` maps to `backstage-cli repo test`. + */ path: string[]; + /** + * A short description of the command, displayed in help output. + */ description: string; + /** + * If `true`, the command is deprecated and will be hidden from help output + * but can still be invoked. + */ deprecated?: boolean; + /** + * If `true`, the command is experimental and will be hidden from help + * output but can still be invoked. + */ experimental?: boolean; + /** + * The command implementation, either as a direct function or as a loader + * that returns the implementation as a default export. The loader form + * is useful for deferring heavy imports until the command is invoked. + * + * @example + * Direct execution: + * ``` + * execute: async ({ args }) => { ... } + * ``` + * + * @example + * Deferred loading: + * ``` + * execute: { loader: () => import('./my-command') } + * ``` + */ execute: | ((context: CommandContext) => Promise) | { @@ -53,14 +108,8 @@ export interface BackstageCommand { } /** - * A CLI feature, currently always a CLI plugin. - * - * @public - */ -export type CliFeature = CliPlugin; - -/** - * A Backstage CLI plugin. + * An opaque representation of a Backstage CLI plugin, created + * using {@link createCliPlugin}. * * @public */ diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index 2d1f94ce79..f63dc330e8 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -16,7 +16,7 @@ import { CommandGraph } from './CommandGraph'; import { OpaqueCliPlugin } from '@internal/cli'; -import type { BackstageCommand, CliFeature } from '@backstage/cli-plugin-api'; +import type { BackstageCommand, CliPlugin } from '@backstage/cli-plugin-api'; import { CommandRegistry } from './CommandRegistry'; import { Command } from 'commander'; import { version } from './version'; @@ -36,12 +36,12 @@ function isNodeHidden( return node.children.every(child => isNodeHidden(child as any)); } -type UninitializedFeature = CliFeature | Promise<{ default: CliFeature }>; +type UninitializedFeature = CliPlugin | Promise<{ default: CliPlugin }>; export class CliInitializer { private graph = new CommandGraph(); private commandRegistry = new CommandRegistry(this.graph); - #uninitiazedFeatures: Promise[] = []; + #uninitiazedFeatures: Promise[] = []; add(feature: UninitializedFeature) { if (isPromise(feature)) { @@ -53,7 +53,7 @@ export class CliInitializer { } } - async #register(feature: CliFeature) { + async #register(feature: CliPlugin) { if (OpaqueCliPlugin.isType(feature)) { const internal = OpaqueCliPlugin.toInternal(feature); for (const command of await internal.commands) { @@ -180,8 +180,8 @@ export class CliInitializer { /** @internal */ export function unwrapFeature( - feature: CliFeature | { default: CliFeature }, -): CliFeature { + feature: CliPlugin | { default: CliPlugin }, +): CliPlugin { if ('$$type' in feature) { return feature; } diff --git a/packages/cli/src/wiring/types.ts b/packages/cli/src/wiring/types.ts index b635e48ac0..98a20427b3 100644 --- a/packages/cli/src/wiring/types.ts +++ b/packages/cli/src/wiring/types.ts @@ -17,6 +17,5 @@ export type { CommandContext, BackstageCommand, - CliFeature, CliPlugin, } from '@backstage/cli-plugin-api'; From a90939e13820551f24929768d8eca986dea17d0f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Mar 2026 22:27:33 +0100 Subject: [PATCH 07/45] Use opaque types for command graph nodes Switch CommandGraph and CliInitializer to use OpaqueCommandTreeNode and OpaqueCommandLeafNode from @internal/cli instead of raw $$type markers. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../cli-internal/src/InternalCommandNode.ts | 54 +++++++++++ packages/cli-internal/src/index.ts | 9 ++ packages/cli/src/wiring/CliInitializer.ts | 52 ++++++----- packages/cli/src/wiring/CommandGraph.ts | 90 +++++++++++-------- 4 files changed, 146 insertions(+), 59 deletions(-) create mode 100644 packages/cli-internal/src/InternalCommandNode.ts diff --git a/packages/cli-internal/src/InternalCommandNode.ts b/packages/cli-internal/src/InternalCommandNode.ts new file mode 100644 index 0000000000..fec79ffb8e --- /dev/null +++ b/packages/cli-internal/src/InternalCommandNode.ts @@ -0,0 +1,54 @@ +/* + * 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 { BackstageCommand } from '@backstage/cli-plugin-api'; +import { OpaqueType } from '@internal/opaque'; + +/** @internal */ +export interface CommandTreeNode { + readonly $$type: '@backstage/CommandTreeNode'; +} + +/** @internal */ +export interface CommandLeafNode { + readonly $$type: '@backstage/CommandLeafNode'; +} + +export type CommandNode = CommandTreeNode | CommandLeafNode; + +export const OpaqueCommandTreeNode = OpaqueType.create<{ + public: CommandTreeNode; + versions: { + readonly version: 'v1'; + readonly name: string; + readonly children: CommandNode[]; + }; +}>({ + type: '@backstage/CommandTreeNode', + versions: ['v1'], +}); + +export const OpaqueCommandLeafNode = OpaqueType.create<{ + public: CommandLeafNode; + versions: { + readonly version: 'v1'; + readonly name: string; + readonly command: BackstageCommand; + }; +}>({ + type: '@backstage/CommandLeafNode', + versions: ['v1'], +}); diff --git a/packages/cli-internal/src/index.ts b/packages/cli-internal/src/index.ts index a1dc8ad24c..578333ee96 100644 --- a/packages/cli-internal/src/index.ts +++ b/packages/cli-internal/src/index.ts @@ -15,3 +15,12 @@ */ export { OpaqueCliPlugin } from './InternalCliPlugin'; +export type { + CommandNode, + CommandTreeNode, + CommandLeafNode, +} from './InternalCommandNode'; +export { + OpaqueCommandTreeNode, + OpaqueCommandLeafNode, +} from './InternalCommandNode'; diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index f63dc330e8..ad9c483d33 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -15,8 +15,13 @@ */ import { CommandGraph } from './CommandGraph'; -import { OpaqueCliPlugin } from '@internal/cli'; -import type { BackstageCommand, CliPlugin } from '@backstage/cli-plugin-api'; +import { + OpaqueCliPlugin, + OpaqueCommandTreeNode, + OpaqueCommandLeafNode, +} from '@internal/cli'; +import type { CommandNode } from '@internal/cli'; +import type { CliPlugin } from '@backstage/cli-plugin-api'; import { CommandRegistry } from './CommandRegistry'; import { Command } from 'commander'; import { version } from './version'; @@ -25,15 +30,13 @@ import { exitWithError } from './errors'; import { ForwardedError } from '@backstage/errors'; import { isPromise } from 'node:util/types'; -function isNodeHidden( - node: - | { $$type: '@tree/leaf'; command: BackstageCommand } - | { $$type: '@tree/root'; children: unknown[] }, -): boolean { - if (node.$$type === '@tree/leaf') { - return !!node.command.deprecated || !!node.command.experimental; +function isNodeHidden(node: CommandNode): boolean { + if (OpaqueCommandLeafNode.isType(node)) { + const { command } = OpaqueCommandLeafNode.toInternal(node); + return !!command.deprecated || !!command.experimental; } - return node.children.every(child => isNodeHidden(child as any)); + const { children } = OpaqueCommandTreeNode.toInternal(node); + return children.every(child => isNodeHidden(child)); } type UninitializedFeature = CliPlugin | Promise<{ default: CliPlugin }>; @@ -92,25 +95,28 @@ export class CliInitializer { })); while (queue.length) { const { node, argParser } = queue.shift()!; - if (node.$$type === '@tree/root') { + if (OpaqueCommandTreeNode.isType(node)) { + const internal = OpaqueCommandTreeNode.toInternal(node); const treeParser = argParser - .command(`${node.name} [command]`, { + .command(`${internal.name} [command]`, { hidden: isNodeHidden(node), }) - .description(node.name); + .description(internal.name); queue.push( - ...node.children.map(child => ({ + ...internal.children.map(child => ({ node: child, argParser: treeParser, })), ); } else { + const internal = OpaqueCommandLeafNode.toInternal(node); argParser - .command(node.name, { - hidden: !!node.command.deprecated || !!node.command.experimental, + .command(internal.name, { + hidden: + !!internal.command.deprecated || !!internal.command.experimental, }) - .description(node.command.description) + .description(internal.command.description) .helpOption(false) .allowUnknownOption(true) .allowExcessArguments(true) @@ -129,7 +135,7 @@ export class CliInitializer { // Skip the command name if ( argIndex === index && - node.command.path[argIndex] === nonProcessArgs[argIndex] + internal.command.path[argIndex] === nonProcessArgs[argIndex] ) { index += 1; continue; @@ -139,15 +145,15 @@ export class CliInitializer { const context = { args: [...positionalArgs, ...args.unknown], info: { - usage: [programName, ...node.command.path].join(' '), - name: node.command.path.join(' '), + usage: [programName, ...internal.command.path].join(' '), + name: internal.command.path.join(' '), }, }; - if (typeof node.command.execute === 'function') { - await node.command.execute(context); + if (typeof internal.command.execute === 'function') { + await internal.command.execute(context); } else { - const mod = await node.command.execute.loader(); + const mod = await internal.command.execute.loader(); // Handle CJS double-wrapping of default exports const fn = typeof mod.default === 'function' diff --git a/packages/cli/src/wiring/CommandGraph.ts b/packages/cli/src/wiring/CommandGraph.ts index a0a2de3305..d64d14b41c 100644 --- a/packages/cli/src/wiring/CommandGraph.ts +++ b/packages/cli/src/wiring/CommandGraph.ts @@ -13,27 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { + CommandNode, + OpaqueCommandTreeNode, + OpaqueCommandLeafNode, +} from '@internal/cli'; import { BackstageCommand } from './types'; -type Node = TreeNode | LeafNode; - -interface TreeNode { - $$type: '@tree/root'; - name: string; - children: TreeNode[]; -} - -interface LeafNode { - $$type: '@tree/leaf'; - name: string; - command: BackstageCommand; -} - /** * A sparse graph of commands. */ export class CommandGraph { - private graph: Node[] = []; + private graph: CommandNode[] = []; /** * Adds a command to the graph. The graph is sparse, so we use the path to determine the nodes @@ -44,28 +35,44 @@ export class CommandGraph { let current = this.graph; for (let i = 0; i < path.length - 1; i++) { const name = path[i]; - let next = current.find(n => n.name === name); + let next = current.find( + n => + (OpaqueCommandTreeNode.isType(n) && + OpaqueCommandTreeNode.toInternal(n).name === name) || + (OpaqueCommandLeafNode.isType(n) && + OpaqueCommandLeafNode.toInternal(n).name === name), + ); if (!next) { - next = { $$type: '@tree/root', name, children: [] }; + next = OpaqueCommandTreeNode.createInstance('v1', { + name, + children: [], + }); current.push(next); - } else if (next.$$type === '@tree/leaf') { + } else if (OpaqueCommandLeafNode.isType(next)) { throw new Error( `Command already exists at path: "${path.slice(0, i).join(' ')}"`, ); } - current = next.children; + current = OpaqueCommandTreeNode.toInternal(next).children; } - const last = current.find(n => n.name === path[path.length - 1]); - if (last && last.$$type === '@tree/leaf') { + const lastName = path[path.length - 1]; + const last = current.find(n => { + if (OpaqueCommandTreeNode.isType(n)) { + return OpaqueCommandTreeNode.toInternal(n).name === lastName; + } + return OpaqueCommandLeafNode.toInternal(n).name === lastName; + }); + if (last && OpaqueCommandLeafNode.isType(last)) { throw new Error( `Command already exists at path: "${path.slice(0, -1).join(' ')}"`, ); } else { - current.push({ - $$type: '@tree/leaf', - name: path[path.length - 1], - command, - }); + current.push( + OpaqueCommandLeafNode.createInstance('v1', { + name: lastName, + command, + }), + ); } } @@ -76,26 +83,37 @@ export class CommandGraph { let current = this.graph; for (let i = 0; i < path.length - 1; i++) { const name = path[i]; - const next = current.find(n => n.name === name); - if (!next) { - return undefined; - } else if (next.$$type === '@tree/leaf') { + const next = current.find(n => { + if (OpaqueCommandTreeNode.isType(n)) { + return OpaqueCommandTreeNode.toInternal(n).name === name; + } + return OpaqueCommandLeafNode.toInternal(n).name === name; + }); + if (!next || OpaqueCommandLeafNode.isType(next)) { return undefined; } - current = next.children; + current = OpaqueCommandTreeNode.toInternal(next).children; } - const last = current.find(n => n.name === path[path.length - 1]); - if (!last || last.$$type === '@tree/root') { + const lastName = path[path.length - 1]; + const last = current.find(n => { + if (OpaqueCommandTreeNode.isType(n)) { + return OpaqueCommandTreeNode.toInternal(n).name === lastName; + } + return OpaqueCommandLeafNode.toInternal(n).name === lastName; + }); + if (!last || OpaqueCommandTreeNode.isType(last)) { return undefined; } - return last?.command; + return OpaqueCommandLeafNode.toInternal(last).command; } - atDepth(depth: number): Node[] { + atDepth(depth: number): CommandNode[] { let current = this.graph; for (let i = 0; i < depth; i++) { current = current.flatMap(n => - n.$$type === '@tree/root' ? n.children : [], + OpaqueCommandTreeNode.isType(n) + ? OpaqueCommandTreeNode.toInternal(n).children + : [], ); } return current; From 7d055ef0c47afe4a6fed43f4a6bb633456a36a5e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Mar 2026 07:39:15 +0100 Subject: [PATCH 08/45] Merge cli-plugin-api into cli-node Move createCliPlugin and related types from the standalone @backstage/cli-plugin-api package into @backstage/cli-node and remove the now-empty package. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/cli-node-add-cli-plugin.md | 5 ++ .changeset/cli-use-cli-plugin-api.md | 2 +- .changeset/create-cli-plugin-api.md | 5 -- packages/cli-internal/package.json | 2 +- .../cli-internal/src/InternalCliPlugin.ts | 2 +- .../cli-internal/src/InternalCommandNode.ts | 2 +- packages/cli-node/report.api.md | 40 +++++++++++++++ .../src/cli-plugin}/createCliPlugin.ts | 2 +- .../src => cli-node/src/cli-plugin}/index.ts | 0 .../src => cli-node/src/cli-plugin}/types.ts | 0 packages/cli-node/src/index.ts | 1 + packages/cli-plugin-api/.eslintrc.js | 1 - packages/cli-plugin-api/catalog-info.yaml | 10 ---- packages/cli-plugin-api/package.json | 39 --------------- packages/cli-plugin-api/report.api.md | 50 ------------------- packages/cli/package.json | 1 - packages/cli/src/modules/build/index.ts | 2 +- packages/cli/src/modules/config/index.ts | 2 +- .../src/modules/create-github-app/index.ts | 2 +- packages/cli/src/modules/info/index.ts | 2 +- packages/cli/src/modules/lint/index.ts | 2 +- packages/cli/src/modules/maintenance/index.ts | 2 +- packages/cli/src/modules/migrate/index.ts | 2 +- packages/cli/src/modules/new/index.ts | 2 +- packages/cli/src/modules/test/index.ts | 2 +- .../cli/src/modules/translations/index.ts | 2 +- packages/cli/src/wiring/CliInitializer.ts | 2 +- packages/cli/src/wiring/factory.ts | 2 +- packages/cli/src/wiring/types.ts | 2 +- yarn.lock | 12 +---- 30 files changed, 65 insertions(+), 135 deletions(-) create mode 100644 .changeset/cli-node-add-cli-plugin.md delete mode 100644 .changeset/create-cli-plugin-api.md rename packages/{cli-plugin-api/src => cli-node/src/cli-plugin}/createCliPlugin.ts (97%) rename packages/{cli-plugin-api/src => cli-node/src/cli-plugin}/index.ts (100%) rename packages/{cli-plugin-api/src => cli-node/src/cli-plugin}/types.ts (100%) delete mode 100644 packages/cli-plugin-api/.eslintrc.js delete mode 100644 packages/cli-plugin-api/catalog-info.yaml delete mode 100644 packages/cli-plugin-api/package.json delete mode 100644 packages/cli-plugin-api/report.api.md diff --git a/.changeset/cli-node-add-cli-plugin.md b/.changeset/cli-node-add-cli-plugin.md new file mode 100644 index 0000000000..b5a26979a9 --- /dev/null +++ b/.changeset/cli-node-add-cli-plugin.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli-node': minor +--- + +Added `createCliPlugin` API and related types for building Backstage CLI plugins. diff --git a/.changeset/cli-use-cli-plugin-api.md b/.changeset/cli-use-cli-plugin-api.md index b55858ba62..cf7f7f12b5 100644 --- a/.changeset/cli-use-cli-plugin-api.md +++ b/.changeset/cli-use-cli-plugin-api.md @@ -2,4 +2,4 @@ '@backstage/cli': patch --- -Migrated CLI plugin modules to use `createCliPlugin` from the new `@backstage/cli-plugin-api` package. +Migrated CLI plugin modules to use `createCliPlugin` from `@backstage/cli-node`. diff --git a/.changeset/create-cli-plugin-api.md b/.changeset/create-cli-plugin-api.md deleted file mode 100644 index d740fe7897..0000000000 --- a/.changeset/create-cli-plugin-api.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli-plugin-api': minor ---- - -Added a new `@backstage/cli-plugin-api` package that provides the `createCliPlugin` API for building Backstage CLI plugins. diff --git a/packages/cli-internal/package.json b/packages/cli-internal/package.json index 80c68c74d3..068735bac3 100644 --- a/packages/cli-internal/package.json +++ b/packages/cli-internal/package.json @@ -22,7 +22,7 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/cli-plugin-api": "workspace:^" + "@backstage/cli-node": "workspace:^" }, "devDependencies": { "@backstage/cli": "workspace:^" diff --git a/packages/cli-internal/src/InternalCliPlugin.ts b/packages/cli-internal/src/InternalCliPlugin.ts index 426f3d23e6..e51b2e3f0e 100644 --- a/packages/cli-internal/src/InternalCliPlugin.ts +++ b/packages/cli-internal/src/InternalCliPlugin.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { BackstageCommand, CliPlugin } from '@backstage/cli-plugin-api'; +import { BackstageCommand, CliPlugin } from '@backstage/cli-node'; import { OpaqueType } from '@internal/opaque'; export const OpaqueCliPlugin = OpaqueType.create<{ diff --git a/packages/cli-internal/src/InternalCommandNode.ts b/packages/cli-internal/src/InternalCommandNode.ts index fec79ffb8e..11147c3373 100644 --- a/packages/cli-internal/src/InternalCommandNode.ts +++ b/packages/cli-internal/src/InternalCommandNode.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { BackstageCommand } from '@backstage/cli-plugin-api'; +import { BackstageCommand } from '@backstage/cli-node'; import { OpaqueType } from '@internal/opaque'; /** @internal */ diff --git a/packages/cli-node/report.api.md b/packages/cli-node/report.api.md index 05d1545ae4..0ce66e7cb5 100644 --- a/packages/cli-node/report.api.md +++ b/packages/cli-node/report.api.md @@ -6,6 +6,21 @@ import { JsonValue } from '@backstage/types'; import { Package } from '@manypkg/get-packages'; +// @public +export interface BackstageCommand { + deprecated?: boolean; + description: string; + execute: + | ((context: CommandContext) => Promise) + | { + loader: () => Promise<{ + default: (context: CommandContext) => Promise; + }>; + }; + experimental?: boolean; + path: string[]; +} + // @public export type BackstagePackage = { dir: string; @@ -86,6 +101,21 @@ export interface BackstagePackageJson { version: string; } +// @public +export interface CliPlugin { + // (undocumented) + readonly $$type: '@backstage/CliPlugin'; +} + +// @public +export interface CommandContext { + args: string[]; + info: { + usage: string; + name: string; + }; +} + // @public export type ConcurrentTasksOptions = { concurrencyFactor?: number; @@ -93,6 +123,16 @@ export type ConcurrentTasksOptions = { worker: (item: TItem) => Promise; }; +// @public +export function createCliPlugin(options: { + packageJson: { + name: string; + }; + init: (registry: { + addCommand: (command: BackstageCommand) => void; + }) => Promise; +}): CliPlugin; + // @public export class GitUtils { static listChangedFiles(ref: string): Promise; diff --git a/packages/cli-plugin-api/src/createCliPlugin.ts b/packages/cli-node/src/cli-plugin/createCliPlugin.ts similarity index 97% rename from packages/cli-plugin-api/src/createCliPlugin.ts rename to packages/cli-node/src/cli-plugin/createCliPlugin.ts index 17ddd8ebb9..f007f74eb4 100644 --- a/packages/cli-plugin-api/src/createCliPlugin.ts +++ b/packages/cli-node/src/cli-plugin/createCliPlugin.ts @@ -26,7 +26,7 @@ import { BackstageCommand, CliPlugin } from './types'; * * @example * ``` - * import { createCliPlugin } from '@backstage/cli-plugin-api'; + * import { createCliPlugin } from '@backstage/cli-node'; * import packageJson from '../package.json'; * * export default createCliPlugin({ diff --git a/packages/cli-plugin-api/src/index.ts b/packages/cli-node/src/cli-plugin/index.ts similarity index 100% rename from packages/cli-plugin-api/src/index.ts rename to packages/cli-node/src/cli-plugin/index.ts diff --git a/packages/cli-plugin-api/src/types.ts b/packages/cli-node/src/cli-plugin/types.ts similarity index 100% rename from packages/cli-plugin-api/src/types.ts rename to packages/cli-node/src/cli-plugin/types.ts diff --git a/packages/cli-node/src/index.ts b/packages/cli-node/src/index.ts index 35074507c4..7c18070bbe 100644 --- a/packages/cli-node/src/index.ts +++ b/packages/cli-node/src/index.ts @@ -21,6 +21,7 @@ */ export * from './cache'; +export * from './cli-plugin'; export * from './concurrency'; export * from './git'; export * from './monorepo'; diff --git a/packages/cli-plugin-api/.eslintrc.js b/packages/cli-plugin-api/.eslintrc.js deleted file mode 100644 index e2a53a6ad2..0000000000 --- a/packages/cli-plugin-api/.eslintrc.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-plugin-api/catalog-info.yaml b/packages/cli-plugin-api/catalog-info.yaml deleted file mode 100644 index 3a0aca14b9..0000000000 --- a/packages/cli-plugin-api/catalog-info.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: backstage-cli-plugin-api - title: '@backstage/cli-plugin-api' - description: API for building Backstage CLI plugins -spec: - lifecycle: experimental - type: backstage-cli-plugin - owner: tooling-maintainers diff --git a/packages/cli-plugin-api/package.json b/packages/cli-plugin-api/package.json deleted file mode 100644 index 4d256f3c96..0000000000 --- a/packages/cli-plugin-api/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "@backstage/cli-plugin-api", - "version": "0.1.0", - "description": "API for building Backstage CLI plugins", - "backstage": { - "role": "cli-plugin" - }, - "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "packages/cli-plugin-api" - }, - "license": "Apache-2.0", - "main": "src/index.ts", - "types": "src/index.ts", - "files": [ - "dist" - ], - "scripts": { - "build": "backstage-cli package build", - "clean": "backstage-cli package clean", - "lint": "backstage-cli package lint", - "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack", - "test": "backstage-cli package test" - }, - "dependencies": { - "@backstage/errors": "workspace:^" - }, - "devDependencies": { - "@backstage/cli": "workspace:^" - } -} diff --git a/packages/cli-plugin-api/report.api.md b/packages/cli-plugin-api/report.api.md deleted file mode 100644 index 0821e01085..0000000000 --- a/packages/cli-plugin-api/report.api.md +++ /dev/null @@ -1,50 +0,0 @@ -## API Report File for "@backstage/cli-plugin-api" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -// @public -export interface BackstageCommand { - deprecated?: boolean; - description: string; - execute: - | ((context: CommandContext) => Promise) - | { - loader: () => Promise<{ - default: (context: CommandContext) => Promise; - }>; - }; - experimental?: boolean; - path: string[]; -} - -// @public -export type CliFeature = CliPlugin; - -// @public -export interface CliPlugin { - // (undocumented) - readonly $$type: '@backstage/CliPlugin'; -} - -// @public -export interface CommandContext { - args: string[]; - info: { - usage: string; - name: string; - }; -} - -// @public -export function createCliPlugin(options: { - packageJson: { - name: string; - }; - init: (registry: { - addCommand: (command: BackstageCommand) => void; - }) => Promise; -}): CliPlugin; - -// (No @packageDocumentation comment for this package) -``` diff --git a/packages/cli/package.json b/packages/cli/package.json index d309e0453c..8e03c60d0f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -50,7 +50,6 @@ "@backstage/catalog-model": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^", - "@backstage/cli-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", "@backstage/errors": "workspace:^", diff --git a/packages/cli/src/modules/build/index.ts b/packages/cli/src/modules/build/index.ts index 1c8d2217ed..e3c04e6325 100644 --- a/packages/cli/src/modules/build/index.ts +++ b/packages/cli/src/modules/build/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export const buildPlugin = createCliPlugin({ diff --git a/packages/cli/src/modules/config/index.ts b/packages/cli/src/modules/config/index.ts index 3c59f96948..e2ddec3678 100644 --- a/packages/cli/src/modules/config/index.ts +++ b/packages/cli/src/modules/config/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export const configOption = [ diff --git a/packages/cli/src/modules/create-github-app/index.ts b/packages/cli/src/modules/create-github-app/index.ts index 69fe5869d4..2171f2ca2e 100644 --- a/packages/cli/src/modules/create-github-app/index.ts +++ b/packages/cli/src/modules/create-github-app/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export default createCliPlugin({ diff --git a/packages/cli/src/modules/info/index.ts b/packages/cli/src/modules/info/index.ts index df8a848f11..b1fa885f03 100644 --- a/packages/cli/src/modules/info/index.ts +++ b/packages/cli/src/modules/info/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export default createCliPlugin({ diff --git a/packages/cli/src/modules/lint/index.ts b/packages/cli/src/modules/lint/index.ts index 51e5b981a4..7da72679d4 100644 --- a/packages/cli/src/modules/lint/index.ts +++ b/packages/cli/src/modules/lint/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export default createCliPlugin({ diff --git a/packages/cli/src/modules/maintenance/index.ts b/packages/cli/src/modules/maintenance/index.ts index 142bd543f2..cf6cf00b2c 100644 --- a/packages/cli/src/modules/maintenance/index.ts +++ b/packages/cli/src/modules/maintenance/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export default createCliPlugin({ diff --git a/packages/cli/src/modules/migrate/index.ts b/packages/cli/src/modules/migrate/index.ts index 603712f8e2..16cf45d244 100644 --- a/packages/cli/src/modules/migrate/index.ts +++ b/packages/cli/src/modules/migrate/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export default createCliPlugin({ diff --git a/packages/cli/src/modules/new/index.ts b/packages/cli/src/modules/new/index.ts index 076a49f9be..9ceb50e272 100644 --- a/packages/cli/src/modules/new/index.ts +++ b/packages/cli/src/modules/new/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import { NotImplementedError } from '@backstage/errors'; import packageJson from '../../../package.json'; diff --git a/packages/cli/src/modules/test/index.ts b/packages/cli/src/modules/test/index.ts index 596572cb9a..07eabbf3f7 100644 --- a/packages/cli/src/modules/test/index.ts +++ b/packages/cli/src/modules/test/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export default createCliPlugin({ diff --git a/packages/cli/src/modules/translations/index.ts b/packages/cli/src/modules/translations/index.ts index 16c19d9345..1903d87684 100644 --- a/packages/cli/src/modules/translations/index.ts +++ b/packages/cli/src/modules/translations/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-plugin-api'; +import { createCliPlugin } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export default createCliPlugin({ diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index ad9c483d33..37156641ee 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -21,7 +21,7 @@ import { OpaqueCommandLeafNode, } from '@internal/cli'; import type { CommandNode } from '@internal/cli'; -import type { CliPlugin } from '@backstage/cli-plugin-api'; +import type { CliPlugin } from '@backstage/cli-node'; import { CommandRegistry } from './CommandRegistry'; import { Command } from 'commander'; import { version } from './version'; diff --git a/packages/cli/src/wiring/factory.ts b/packages/cli/src/wiring/factory.ts index 19c68e805f..e840e694c6 100644 --- a/packages/cli/src/wiring/factory.ts +++ b/packages/cli/src/wiring/factory.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { createCliPlugin } from '@backstage/cli-plugin-api'; +export { createCliPlugin } from '@backstage/cli-node'; diff --git a/packages/cli/src/wiring/types.ts b/packages/cli/src/wiring/types.ts index 98a20427b3..04eedfbd0d 100644 --- a/packages/cli/src/wiring/types.ts +++ b/packages/cli/src/wiring/types.ts @@ -18,4 +18,4 @@ export type { CommandContext, BackstageCommand, CliPlugin, -} from '@backstage/cli-plugin-api'; +} from '@backstage/cli-node'; diff --git a/yarn.lock b/yarn.lock index 2ef9ed9764..7465a75f4d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2822,15 +2822,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-plugin-api@workspace:^, @backstage/cli-plugin-api@workspace:packages/cli-plugin-api": - version: 0.0.0-use.local - resolution: "@backstage/cli-plugin-api@workspace:packages/cli-plugin-api" - dependencies: - "@backstage/cli": "workspace:^" - "@backstage/errors": "workspace:^" - languageName: unknown - linkType: soft - "@backstage/cli@workspace:*, @backstage/cli@workspace:^, @backstage/cli@workspace:packages/cli": version: 0.0.0-use.local resolution: "@backstage/cli@workspace:packages/cli" @@ -2841,7 +2832,6 @@ __metadata: "@backstage/catalog-model": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" - "@backstage/cli-plugin-api": "workspace:^" "@backstage/config": "workspace:^" "@backstage/config-loader": "workspace:^" "@backstage/core-app-api": "workspace:^" @@ -9685,7 +9675,7 @@ __metadata: resolution: "@internal/cli@workspace:packages/cli-internal" dependencies: "@backstage/cli": "workspace:^" - "@backstage/cli-plugin-api": "workspace:^" + "@backstage/cli-node": "workspace:^" languageName: unknown linkType: soft From 1929a95b97ea1eb635ee4d73894e7bcb1c4ef122 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Mar 2026 07:46:09 +0100 Subject: [PATCH 09/45] Rename BackstageCommand to CliCommand and CommandContext to CliCommandContext Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../cli-internal/src/InternalCliPlugin.ts | 4 +- .../cli-internal/src/InternalCommandNode.ts | 4 +- packages/cli-node/report.api.md | 40 +++++++++---------- .../src/cli-plugin/createCliPlugin.ts | 6 +-- packages/cli-node/src/cli-plugin/index.ts | 2 +- packages/cli-node/src/cli-plugin/types.ts | 8 ++-- .../cli/src/modules/auth/commands/list.ts | 4 +- .../cli/src/modules/auth/commands/login.ts | 4 +- .../cli/src/modules/auth/commands/logout.ts | 4 +- .../src/modules/auth/commands/printToken.ts | 4 +- .../cli/src/modules/auth/commands/select.ts | 4 +- .../cli/src/modules/auth/commands/show.ts | 4 +- .../modules/build/commands/buildWorkspace.ts | 4 +- .../build/commands/package/build/command.ts | 4 +- .../modules/build/commands/package/clean.ts | 4 +- .../build/commands/package/postpack.ts | 4 +- .../modules/build/commands/package/prepack.ts | 4 +- .../build/commands/package/start/command.ts | 4 +- .../src/modules/build/commands/repo/build.ts | 4 +- .../src/modules/build/commands/repo/clean.ts | 4 +- .../src/modules/build/commands/repo/start.ts | 4 +- .../cli/src/modules/config/commands/docs.ts | 4 +- .../cli/src/modules/config/commands/print.ts | 4 +- .../cli/src/modules/config/commands/schema.ts | 4 +- .../src/modules/config/commands/validate.ts | 4 +- .../commands/create-github-app/index.ts | 4 +- .../cli/src/modules/info/commands/info.ts | 4 +- .../src/modules/lint/commands/package/lint.ts | 4 +- .../src/modules/lint/commands/repo/lint.ts | 4 +- .../modules/maintenance/commands/repo/fix.ts | 2 +- .../commands/repo/list-deprecations.ts | 4 +- .../migrate/commands/packageExports.ts | 4 +- .../migrate/commands/packageLintConfigs.ts | 4 +- .../modules/migrate/commands/packageRole.ts | 4 +- .../migrate/commands/packageScripts.ts | 4 +- .../migrate/commands/reactRouterDeps.ts | 4 +- .../modules/migrate/commands/versions/bump.ts | 4 +- .../migrate/commands/versions/migrate.ts | 4 +- .../cli/src/modules/new/commands/new.test.ts | 4 +- packages/cli/src/modules/new/commands/new.ts | 4 +- .../src/modules/test/commands/package/test.ts | 4 +- .../src/modules/test/commands/repo/test.ts | 4 +- .../modules/translations/commands/export.ts | 4 +- .../modules/translations/commands/import.ts | 4 +- packages/cli/src/wiring/CommandGraph.ts | 6 +-- packages/cli/src/wiring/CommandRegistry.ts | 4 +- packages/cli/src/wiring/types.ts | 4 +- 47 files changed, 114 insertions(+), 114 deletions(-) diff --git a/packages/cli-internal/src/InternalCliPlugin.ts b/packages/cli-internal/src/InternalCliPlugin.ts index e51b2e3f0e..4491e5d7c1 100644 --- a/packages/cli-internal/src/InternalCliPlugin.ts +++ b/packages/cli-internal/src/InternalCliPlugin.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { BackstageCommand, CliPlugin } from '@backstage/cli-node'; +import { CliCommand, CliPlugin } from '@backstage/cli-node'; import { OpaqueType } from '@internal/opaque'; export const OpaqueCliPlugin = OpaqueType.create<{ @@ -22,7 +22,7 @@ export const OpaqueCliPlugin = OpaqueType.create<{ versions: { readonly version: 'v1'; readonly packageName: string; - readonly commands: Promise>; + readonly commands: Promise>; }; }>({ type: '@backstage/CliPlugin', diff --git a/packages/cli-internal/src/InternalCommandNode.ts b/packages/cli-internal/src/InternalCommandNode.ts index 11147c3373..3d93a5128d 100644 --- a/packages/cli-internal/src/InternalCommandNode.ts +++ b/packages/cli-internal/src/InternalCommandNode.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { BackstageCommand } from '@backstage/cli-node'; +import { CliCommand } from '@backstage/cli-node'; import { OpaqueType } from '@internal/opaque'; /** @internal */ @@ -46,7 +46,7 @@ export const OpaqueCommandLeafNode = OpaqueType.create<{ versions: { readonly version: 'v1'; readonly name: string; - readonly command: BackstageCommand; + readonly command: CliCommand; }; }>({ type: '@backstage/CommandLeafNode', diff --git a/packages/cli-node/report.api.md b/packages/cli-node/report.api.md index 0ce66e7cb5..d2d4db856d 100644 --- a/packages/cli-node/report.api.md +++ b/packages/cli-node/report.api.md @@ -6,21 +6,6 @@ import { JsonValue } from '@backstage/types'; import { Package } from '@manypkg/get-packages'; -// @public -export interface BackstageCommand { - deprecated?: boolean; - description: string; - execute: - | ((context: CommandContext) => Promise) - | { - loader: () => Promise<{ - default: (context: CommandContext) => Promise; - }>; - }; - experimental?: boolean; - path: string[]; -} - // @public export type BackstagePackage = { dir: string; @@ -102,13 +87,22 @@ export interface BackstagePackageJson { } // @public -export interface CliPlugin { - // (undocumented) - readonly $$type: '@backstage/CliPlugin'; +export interface CliCommand { + deprecated?: boolean; + description: string; + execute: + | ((context: CliCommandContext) => Promise) + | { + loader: () => Promise<{ + default: (context: CliCommandContext) => Promise; + }>; + }; + experimental?: boolean; + path: string[]; } // @public -export interface CommandContext { +export interface CliCommandContext { args: string[]; info: { usage: string; @@ -116,6 +110,12 @@ export interface CommandContext { }; } +// @public +export interface CliPlugin { + // (undocumented) + readonly $$type: '@backstage/CliPlugin'; +} + // @public export type ConcurrentTasksOptions = { concurrencyFactor?: number; @@ -129,7 +129,7 @@ export function createCliPlugin(options: { name: string; }; init: (registry: { - addCommand: (command: BackstageCommand) => void; + addCommand: (command: CliCommand) => void; }) => Promise; }): CliPlugin; diff --git a/packages/cli-node/src/cli-plugin/createCliPlugin.ts b/packages/cli-node/src/cli-plugin/createCliPlugin.ts index f007f74eb4..dcb79e0b3f 100644 --- a/packages/cli-node/src/cli-plugin/createCliPlugin.ts +++ b/packages/cli-node/src/cli-plugin/createCliPlugin.ts @@ -15,7 +15,7 @@ */ import { OpaqueCliPlugin } from '@internal/cli'; -import { BackstageCommand, CliPlugin } from './types'; +import { CliCommand, CliPlugin } from './types'; /** * Creates a new CLI plugin that provides commands to the Backstage CLI. @@ -52,10 +52,10 @@ export function createCliPlugin(options: { */ init: (registry: { /** Registers a new command with the CLI. */ - addCommand: (command: BackstageCommand) => void; + addCommand: (command: CliCommand) => void; }) => Promise; }): CliPlugin { - const commands: BackstageCommand[] = []; + const commands: CliCommand[] = []; const commandsPromise = options .init({ addCommand: command => commands.push(command) }) .then(() => commands); diff --git a/packages/cli-node/src/cli-plugin/index.ts b/packages/cli-node/src/cli-plugin/index.ts index 723b0edd55..df8b340c50 100644 --- a/packages/cli-node/src/cli-plugin/index.ts +++ b/packages/cli-node/src/cli-plugin/index.ts @@ -15,4 +15,4 @@ */ export { createCliPlugin } from './createCliPlugin'; -export type { BackstageCommand, CommandContext, CliPlugin } from './types'; +export type { CliCommand, CliCommandContext, CliPlugin } from './types'; diff --git a/packages/cli-node/src/cli-plugin/types.ts b/packages/cli-node/src/cli-plugin/types.ts index cdb6d886ee..21dac09eb9 100644 --- a/packages/cli-node/src/cli-plugin/types.ts +++ b/packages/cli-node/src/cli-plugin/types.ts @@ -21,7 +21,7 @@ * * @public */ -export interface CommandContext { +export interface CliCommandContext { /** * The remaining arguments passed to the command after the command path * has been resolved. This includes both positional arguments and flags. @@ -61,7 +61,7 @@ export interface CommandContext { * * @public */ -export interface BackstageCommand { +export interface CliCommand { /** * The path segments that define the command's position in the CLI tree. * For example, `['repo', 'test']` maps to `backstage-cli repo test`. @@ -99,10 +99,10 @@ export interface BackstageCommand { * ``` */ execute: - | ((context: CommandContext) => Promise) + | ((context: CliCommandContext) => Promise) | { loader: () => Promise<{ - default: (context: CommandContext) => Promise; + default: (context: CliCommandContext) => Promise; }>; }; } diff --git a/packages/cli/src/modules/auth/commands/list.ts b/packages/cli/src/modules/auth/commands/list.ts index c245072c88..c27aace3ce 100644 --- a/packages/cli/src/modules/auth/commands/list.ts +++ b/packages/cli/src/modules/auth/commands/list.ts @@ -15,10 +15,10 @@ */ import { cli } from 'cleye'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; import { getAllInstances } from '../lib/storage'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info }, undefined, args); const { instances, selected } = await getAllInstances(); diff --git a/packages/cli/src/modules/auth/commands/login.ts b/packages/cli/src/modules/auth/commands/login.ts index 777fcb1807..8bdd9e0c36 100644 --- a/packages/cli/src/modules/auth/commands/login.ts +++ b/packages/cli/src/modules/auth/commands/login.ts @@ -15,7 +15,7 @@ */ import { cli } from 'cleye'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; import { startCallbackServer } from '../lib/localServer'; import { spawn } from 'node:child_process'; import { challengeFromVerifier, generateVerifier } from '../lib/pkce'; @@ -37,7 +37,7 @@ import inquirer from 'inquirer'; const TOKEN_EXCHANGE_TIMEOUT_MS = 30_000; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { backendUrl, noBrowser, instance: instanceFlag }, } = cli( diff --git a/packages/cli/src/modules/auth/commands/logout.ts b/packages/cli/src/modules/auth/commands/logout.ts index 8277ea6335..ef2e0171b9 100644 --- a/packages/cli/src/modules/auth/commands/logout.ts +++ b/packages/cli/src/modules/auth/commands/logout.ts @@ -15,7 +15,7 @@ */ import { cli } from 'cleye'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; import { getSecretStore } from '../lib/secretStore'; import { removeInstance, @@ -25,7 +25,7 @@ import { import { httpJson } from '../lib/http'; import { pickInstance } from '../lib/prompt'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { instance: instanceFlag }, } = cli( diff --git a/packages/cli/src/modules/auth/commands/printToken.ts b/packages/cli/src/modules/auth/commands/printToken.ts index ea848a112a..e857e39779 100644 --- a/packages/cli/src/modules/auth/commands/printToken.ts +++ b/packages/cli/src/modules/auth/commands/printToken.ts @@ -15,12 +15,12 @@ */ import { cli } from 'cleye'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; import { accessTokenNeedsRefresh, refreshAccessToken } from '../lib/auth'; import { getSelectedInstance } from '../lib/storage'; import { getSecretStore } from '../lib/secretStore'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { instance: instanceFlag }, } = cli( diff --git a/packages/cli/src/modules/auth/commands/select.ts b/packages/cli/src/modules/auth/commands/select.ts index 839fee691e..713b293723 100644 --- a/packages/cli/src/modules/auth/commands/select.ts +++ b/packages/cli/src/modules/auth/commands/select.ts @@ -15,11 +15,11 @@ */ import { cli } from 'cleye'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; import { setSelectedInstance } from '../lib/storage'; import { pickInstance } from '../lib/prompt'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { instance: instanceFlag }, } = cli( diff --git a/packages/cli/src/modules/auth/commands/show.ts b/packages/cli/src/modules/auth/commands/show.ts index cd55430f91..8f4ffacfe0 100644 --- a/packages/cli/src/modules/auth/commands/show.ts +++ b/packages/cli/src/modules/auth/commands/show.ts @@ -15,13 +15,13 @@ */ import { cli } from 'cleye'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; import { httpJson } from '../lib/http'; import { getSelectedInstance } from '../lib/storage'; import { accessTokenNeedsRefresh, refreshAccessToken } from '../lib/auth'; import { getSecretStore } from '../lib/secretStore'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { instance: instanceFlag }, } = cli( diff --git a/packages/cli/src/modules/build/commands/buildWorkspace.ts b/packages/cli/src/modules/build/commands/buildWorkspace.ts index f9ca19962f..fd1ebe16e6 100644 --- a/packages/cli/src/modules/build/commands/buildWorkspace.ts +++ b/packages/cli/src/modules/build/commands/buildWorkspace.ts @@ -17,9 +17,9 @@ import fs from 'fs-extra'; import { cli } from 'cleye'; import { createDistWorkspace } from '../lib/packager'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { // Normalize legacy --alwaysYarnPack alias (a genuinely different name, not // just a casing variant — type-flag handles camelCase/kebab-case natively) const normalizedArgs = args.map(a => { diff --git a/packages/cli/src/modules/build/commands/package/build/command.ts b/packages/cli/src/modules/build/commands/package/build/command.ts index 7a6280299b..a5ba12ea21 100644 --- a/packages/cli/src/modules/build/commands/package/build/command.ts +++ b/packages/cli/src/modules/build/commands/package/build/command.ts @@ -29,9 +29,9 @@ import { buildFrontend } from '../../../lib/buildFrontend'; import { buildBackend } from '../../../lib/buildBackend'; import { isValidUrl } from '../../../lib/urls'; import chalk from 'chalk'; -import type { CommandContext } from '../../../../../wiring/types'; +import type { CliCommandContext } from '../../../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { role, diff --git a/packages/cli/src/modules/build/commands/package/clean.ts b/packages/cli/src/modules/build/commands/package/clean.ts index 6aa987f6c1..9e7ca53d86 100644 --- a/packages/cli/src/modules/build/commands/package/clean.ts +++ b/packages/cli/src/modules/build/commands/package/clean.ts @@ -17,9 +17,9 @@ import { cli } from 'cleye'; import fs from 'fs-extra'; import { targetPaths } from '@backstage/cli-common'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); await fs.remove(targetPaths.resolve('dist')); await fs.remove(targetPaths.resolve('dist-types')); diff --git a/packages/cli/src/modules/build/commands/package/postpack.ts b/packages/cli/src/modules/build/commands/package/postpack.ts index 232d03af6b..a4c64b6071 100644 --- a/packages/cli/src/modules/build/commands/package/postpack.ts +++ b/packages/cli/src/modules/build/commands/package/postpack.ts @@ -17,9 +17,9 @@ import { cli } from 'cleye'; import { targetPaths } from '@backstage/cli-common'; import { revertProductionPack } from '../../lib/packager/productionPack'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); await revertProductionPack(targetPaths.dir); }; diff --git a/packages/cli/src/modules/build/commands/package/prepack.ts b/packages/cli/src/modules/build/commands/package/prepack.ts index e6aba2ce3f..8a41f164b8 100644 --- a/packages/cli/src/modules/build/commands/package/prepack.ts +++ b/packages/cli/src/modules/build/commands/package/prepack.ts @@ -20,9 +20,9 @@ import { targetPaths } from '@backstage/cli-common'; import { productionPack } from '../../lib/packager/productionPack'; import { publishPreflightCheck } from '../../lib/publishing'; import { createTypeDistProject } from '../../lib/typeDistProject'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); publishPreflightCheck({ diff --git a/packages/cli/src/modules/build/commands/package/start/command.ts b/packages/cli/src/modules/build/commands/package/start/command.ts index fe871973de..56adb3889b 100644 --- a/packages/cli/src/modules/build/commands/package/start/command.ts +++ b/packages/cli/src/modules/build/commands/package/start/command.ts @@ -19,9 +19,9 @@ import { startPackage } from './startPackage'; import { resolveLinkedWorkspace } from './resolveLinkedWorkspace'; import { findRoleFromCommand } from '../../../lib/role'; import { targetPaths } from '@backstage/cli-common'; -import type { CommandContext } from '../../../../../wiring/types'; +import type { CliCommandContext } from '../../../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { config, diff --git a/packages/cli/src/modules/build/commands/repo/build.ts b/packages/cli/src/modules/build/commands/repo/build.ts index 7140310464..7587ca0cc7 100644 --- a/packages/cli/src/modules/build/commands/repo/build.ts +++ b/packages/cli/src/modules/build/commands/repo/build.ts @@ -29,9 +29,9 @@ import { import { buildFrontend } from '../../lib/buildFrontend'; import { buildBackend } from '../../lib/buildBackend'; import { createScriptOptionsParser } from '../../lib/optionsParser'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { all, since, minify }, } = cli( diff --git a/packages/cli/src/modules/build/commands/repo/clean.ts b/packages/cli/src/modules/build/commands/repo/clean.ts index 7814c1e4b7..99a6d0a77a 100644 --- a/packages/cli/src/modules/build/commands/repo/clean.ts +++ b/packages/cli/src/modules/build/commands/repo/clean.ts @@ -19,9 +19,9 @@ import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; import { PackageGraph } from '@backstage/cli-node'; import { run, targetPaths } from '@backstage/cli-common'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); const packages = await PackageGraph.listTargetPackages(); diff --git a/packages/cli/src/modules/build/commands/repo/start.ts b/packages/cli/src/modules/build/commands/repo/start.ts index e4c51a1e46..ab8d8f9279 100644 --- a/packages/cli/src/modules/build/commands/repo/start.ts +++ b/packages/cli/src/modules/build/commands/repo/start.ts @@ -26,7 +26,7 @@ import { cli } from 'cleye'; import { resolveLinkedWorkspace } from '../package/start/resolveLinkedWorkspace'; import { startPackage } from '../package/start/startPackage'; import { parseArgs } from 'node:util'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; const ACCEPTED_PACKAGE_ROLES: Array = [ 'frontend', @@ -35,7 +35,7 @@ const ACCEPTED_PACKAGE_ROLES: Array = [ 'backend-plugin', ]; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { plugin, config, require: requirePath, link, inspect, inspectBrk }, _: namesOrPaths, diff --git a/packages/cli/src/modules/config/commands/docs.ts b/packages/cli/src/modules/config/commands/docs.ts index 84d2f384e1..ff9955ddba 100644 --- a/packages/cli/src/modules/config/commands/docs.ts +++ b/packages/cli/src/modules/config/commands/docs.ts @@ -21,11 +21,11 @@ import { JSONSchema7 as JSONSchema } from 'json-schema'; import openBrowser from 'react-dev-utils/openBrowser'; import chalk from 'chalk'; import { loadCliConfig } from '../lib/config'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; const DOCS_URL = 'https://config.backstage.io'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { package: pkg }, } = cli( diff --git a/packages/cli/src/modules/config/commands/print.ts b/packages/cli/src/modules/config/commands/print.ts index 33f7245604..fdde6fcb5d 100644 --- a/packages/cli/src/modules/config/commands/print.ts +++ b/packages/cli/src/modules/config/commands/print.ts @@ -19,9 +19,9 @@ import { stringify as stringifyYaml } from 'yaml'; import { AppConfig, ConfigReader } from '@backstage/config'; import { loadCliConfig } from '../lib/config'; import { ConfigSchema, ConfigVisibility } from '@backstage/config-loader'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { config, lax, frontend, withSecrets, format, package: pkg }, } = cli( diff --git a/packages/cli/src/modules/config/commands/schema.ts b/packages/cli/src/modules/config/commands/schema.ts index 13f651534c..989fcdbc26 100644 --- a/packages/cli/src/modules/config/commands/schema.ts +++ b/packages/cli/src/modules/config/commands/schema.ts @@ -20,9 +20,9 @@ import { stringify as stringifyYaml } from 'yaml'; import { loadCliConfig } from '../lib/config'; import { JsonObject } from '@backstage/types'; import { mergeConfigSchemas } from '@backstage/config-loader'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { merge, format, package: pkg }, } = cli( diff --git a/packages/cli/src/modules/config/commands/validate.ts b/packages/cli/src/modules/config/commands/validate.ts index f6cf9cc662..78505f76bf 100644 --- a/packages/cli/src/modules/config/commands/validate.ts +++ b/packages/cli/src/modules/config/commands/validate.ts @@ -16,9 +16,9 @@ import { cli } from 'cleye'; import { loadCliConfig } from '../lib/config'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { config, lax, frontend, deprecated, strict, package: pkg }, } = cli( diff --git a/packages/cli/src/modules/create-github-app/commands/create-github-app/index.ts b/packages/cli/src/modules/create-github-app/commands/create-github-app/index.ts index 9dd9f4c4c4..25f3847b42 100644 --- a/packages/cli/src/modules/create-github-app/commands/create-github-app/index.ts +++ b/packages/cli/src/modules/create-github-app/commands/create-github-app/index.ts @@ -23,12 +23,12 @@ import { cli } from 'cleye'; import { GithubCreateAppServer } from './GithubCreateAppServer'; import openBrowser from 'react-dev-utils/openBrowser'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; // This is an experimental command that at this point does not support GitHub Enterprise // due to lacking support for creating apps from manifests. // https://docs.github.com/en/free-pro-team@latest/developers/apps/creating-a-github-app-from-a-manifest -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { _: positionals } = cli( { help: { ...info, usage: `${info.usage} ` }, diff --git a/packages/cli/src/modules/info/commands/info.ts b/packages/cli/src/modules/info/commands/info.ts index ab26714fca..306bb54f4a 100644 --- a/packages/cli/src/modules/info/commands/info.ts +++ b/packages/cli/src/modules/info/commands/info.ts @@ -25,7 +25,7 @@ import { } from '@backstage/cli-node'; import { minimatch } from 'minimatch'; import fs from 'fs-extra'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; /** * Attempts to read package.json from node_modules for a given package name. @@ -52,7 +52,7 @@ function hasBackstageField(packageName: string, targetPath: string): boolean { return pkg?.backstage !== undefined; } -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { include, format }, } = cli( diff --git a/packages/cli/src/modules/lint/commands/package/lint.ts b/packages/cli/src/modules/lint/commands/package/lint.ts index 39c74bab73..de6716ec0a 100644 --- a/packages/cli/src/modules/lint/commands/package/lint.ts +++ b/packages/cli/src/modules/lint/commands/package/lint.ts @@ -18,9 +18,9 @@ import fs from 'fs-extra'; import { cli } from 'cleye'; import { targetPaths } from '@backstage/cli-common'; import { ESLint } from 'eslint'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { fix, format, outputFile, maxWarnings }, _: directories, diff --git a/packages/cli/src/modules/lint/commands/repo/lint.ts b/packages/cli/src/modules/lint/commands/repo/lint.ts index 5ce4be72f8..1598c44c54 100644 --- a/packages/cli/src/modules/lint/commands/repo/lint.ts +++ b/packages/cli/src/modules/lint/commands/repo/lint.ts @@ -29,7 +29,7 @@ import { import { targetPaths } from '@backstage/cli-common'; import { createScriptOptionsParser } from '../../lib/optionsParser'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; function depCount(pkg: BackstagePackageJson) { const deps = pkg.dependencies ? Object.keys(pkg.dependencies).length : 0; @@ -39,7 +39,7 @@ function depCount(pkg: BackstagePackageJson) { return deps + devDeps; } -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { for (const flag of [ 'outputFile', 'successCache', diff --git a/packages/cli/src/modules/maintenance/commands/repo/fix.ts b/packages/cli/src/modules/maintenance/commands/repo/fix.ts index 324b4c6a3f..d3e0759afc 100644 --- a/packages/cli/src/modules/maintenance/commands/repo/fix.ts +++ b/packages/cli/src/modules/maintenance/commands/repo/fix.ts @@ -505,7 +505,7 @@ type PackageFixer = (pkg: FixablePackage, packages: FixablePackage[]) => void; export default async ({ args, info, -}: import('../../../../wiring/types').CommandContext) => { +}: import('../../../../wiring/types').CliCommandContext) => { const { flags: { publish, check }, } = cli( diff --git a/packages/cli/src/modules/maintenance/commands/repo/list-deprecations.ts b/packages/cli/src/modules/maintenance/commands/repo/list-deprecations.ts index 23f64463cb..b594920027 100644 --- a/packages/cli/src/modules/maintenance/commands/repo/list-deprecations.ts +++ b/packages/cli/src/modules/maintenance/commands/repo/list-deprecations.ts @@ -20,9 +20,9 @@ import { cli } from 'cleye'; import { relative as relativePath } from 'node:path'; import { PackageGraph } from '@backstage/cli-node'; import { targetPaths } from '@backstage/cli-common'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { json }, } = cli( diff --git a/packages/cli/src/modules/migrate/commands/packageExports.ts b/packages/cli/src/modules/migrate/commands/packageExports.ts index 7fe6a49b35..68cb14a01e 100644 --- a/packages/cli/src/modules/migrate/commands/packageExports.ts +++ b/packages/cli/src/modules/migrate/commands/packageExports.ts @@ -15,9 +15,9 @@ */ import { cli } from 'cleye'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); throw new Error( 'The `migrate package-exports` command has been removed, use `repo fix` instead.', diff --git a/packages/cli/src/modules/migrate/commands/packageLintConfigs.ts b/packages/cli/src/modules/migrate/commands/packageLintConfigs.ts index 73cbe380ec..be316b0bf5 100644 --- a/packages/cli/src/modules/migrate/commands/packageLintConfigs.ts +++ b/packages/cli/src/modules/migrate/commands/packageLintConfigs.ts @@ -19,11 +19,11 @@ import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; import { PackageGraph } from '@backstage/cli-node'; import { runOutput } from '@backstage/cli-common'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; const PREFIX = `module.exports = require('@backstage/cli/config/eslint-factory')`; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); const packages = await PackageGraph.listTargetPackages(); diff --git a/packages/cli/src/modules/migrate/commands/packageRole.ts b/packages/cli/src/modules/migrate/commands/packageRole.ts index cc909a351c..d9f775e2d0 100644 --- a/packages/cli/src/modules/migrate/commands/packageRole.ts +++ b/packages/cli/src/modules/migrate/commands/packageRole.ts @@ -20,9 +20,9 @@ import { resolve as resolvePath } from 'node:path'; import { getPackages } from '@manypkg/get-packages'; import { PackageRoles } from '@backstage/cli-node'; import { targetPaths } from '@backstage/cli-common'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); const { packages } = await getPackages(targetPaths.dir); diff --git a/packages/cli/src/modules/migrate/commands/packageScripts.ts b/packages/cli/src/modules/migrate/commands/packageScripts.ts index f9b4b56591..80810f31fc 100644 --- a/packages/cli/src/modules/migrate/commands/packageScripts.ts +++ b/packages/cli/src/modules/migrate/commands/packageScripts.ts @@ -18,13 +18,13 @@ import { cli } from 'cleye'; import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; import { PackageGraph, PackageRoles, PackageRole } from '@backstage/cli-node'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; const configArgPattern = /--config[=\s][^\s$]+/; const noStartRoles: PackageRole[] = ['cli', 'cli-plugin', 'common-library']; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); const packages = await PackageGraph.listTargetPackages(); diff --git a/packages/cli/src/modules/migrate/commands/reactRouterDeps.ts b/packages/cli/src/modules/migrate/commands/reactRouterDeps.ts index b2208e2dc4..e5a12de3cd 100644 --- a/packages/cli/src/modules/migrate/commands/reactRouterDeps.ts +++ b/packages/cli/src/modules/migrate/commands/reactRouterDeps.ts @@ -18,12 +18,12 @@ import { cli } from 'cleye'; import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; import { PackageGraph, PackageRoles } from '@backstage/cli-node'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; const REACT_ROUTER_DEPS = ['react-router', 'react-router-dom']; const REACT_ROUTER_RANGE = '6.0.0-beta.0 || ^6.3.0'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); const packages = await PackageGraph.listTargetPackages(); diff --git a/packages/cli/src/modules/migrate/commands/versions/bump.ts b/packages/cli/src/modules/migrate/commands/versions/bump.ts index 8048c21505..0142e63985 100644 --- a/packages/cli/src/modules/migrate/commands/versions/bump.ts +++ b/packages/cli/src/modules/migrate/commands/versions/bump.ts @@ -48,7 +48,7 @@ import { import { migrateMovedPackages } from './migrate'; import { runYarnInstall } from '../../lib/utils'; import { run } from '@backstage/cli-common'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; const DEP_TYPES = [ 'dependencies', @@ -74,7 +74,7 @@ function extendsDefaultPattern(pattern: string): boolean { return minimatch('@backstage/', pattern.slice(0, -1)); } -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { pattern: patternFlag, release, skipInstall, skipMigrate }, } = cli( diff --git a/packages/cli/src/modules/migrate/commands/versions/migrate.ts b/packages/cli/src/modules/migrate/commands/versions/migrate.ts index 1286af015e..eb0596d2af 100644 --- a/packages/cli/src/modules/migrate/commands/versions/migrate.ts +++ b/packages/cli/src/modules/migrate/commands/versions/migrate.ts @@ -21,7 +21,7 @@ import { readJson, writeJson } from 'fs-extra'; import { minimatch } from 'minimatch'; import { runYarnInstall } from '../../lib/utils'; import replace from 'replace-in-file'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; declare module 'replace-in-file' { export default function (config: { @@ -39,7 +39,7 @@ declare module 'replace-in-file' { >; } -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { pattern, skipCodeChanges }, } = cli( diff --git a/packages/cli/src/modules/new/commands/new.test.ts b/packages/cli/src/modules/new/commands/new.test.ts index 9a490e8f9a..463add855d 100644 --- a/packages/cli/src/modules/new/commands/new.test.ts +++ b/packages/cli/src/modules/new/commands/new.test.ts @@ -16,7 +16,7 @@ import { createNewPackage } from '../lib/createNewPackage'; import { default as newCommand } from './new'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; jest.mock('../lib/createNewPackage'); @@ -39,7 +39,7 @@ describe.each([ if (scope) { args.push('--scope', scope); } - const context: CommandContext = { + const context: CliCommandContext = { args, info: { usage: 'backstage-cli new', name: 'new' }, }; diff --git a/packages/cli/src/modules/new/commands/new.ts b/packages/cli/src/modules/new/commands/new.ts index 3769e19269..296a3a321e 100644 --- a/packages/cli/src/modules/new/commands/new.ts +++ b/packages/cli/src/modules/new/commands/new.ts @@ -16,9 +16,9 @@ import { cli } from 'cleye'; import { createNewPackage } from '../lib/createNewPackage'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { for (const flag of ['skipInstall', 'npmRegistry', 'baseVersion']) { if (args.some(a => a === `--${flag}` || a.startsWith(`--${flag}=`))) { process.stderr.write( diff --git a/packages/cli/src/modules/test/commands/package/test.ts b/packages/cli/src/modules/test/commands/package/test.ts index 687b66dbfd..b57ae909be 100644 --- a/packages/cli/src/modules/test/commands/package/test.ts +++ b/packages/cli/src/modules/test/commands/package/test.ts @@ -15,7 +15,7 @@ */ import { runCheck, findOwnPaths } from '@backstage/cli-common'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; function includesAnyOf(hayStack: string[], ...needles: string[]) { for (const needle of needles) { @@ -26,7 +26,7 @@ function includesAnyOf(hayStack: string[], ...needles: string[]) { return false; } -export default async ({ args }: CommandContext) => { +export default async ({ args }: CliCommandContext) => { // Only include our config if caller isn't passing their own config if (!includesAnyOf(args, '-c', '--config')) { /* eslint-disable-next-line no-restricted-syntax */ diff --git a/packages/cli/src/modules/test/commands/repo/test.ts b/packages/cli/src/modules/test/commands/repo/test.ts index 1c39415192..adcaf99dfd 100644 --- a/packages/cli/src/modules/test/commands/repo/test.ts +++ b/packages/cli/src/modules/test/commands/repo/test.ts @@ -31,7 +31,7 @@ import { findOwnPaths, isChildPath, } from '@backstage/cli-common'; -import type { CommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '../../../../wiring/types'; type JestProject = { displayName: string; @@ -131,7 +131,7 @@ export function createFlagFinder(args: string[]) { }; } -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const testGlobal = global as TestGlobal; for (const flag of ['successCache', 'successCacheDir', 'jestHelp']) { diff --git a/packages/cli/src/modules/translations/commands/export.ts b/packages/cli/src/modules/translations/commands/export.ts index b6471f10f4..ca496ad859 100644 --- a/packages/cli/src/modules/translations/commands/export.ts +++ b/packages/cli/src/modules/translations/commands/export.ts @@ -33,9 +33,9 @@ import { formatMessagePath, validatePattern, } from '../lib/messageFilePath'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { output, pattern }, } = cli( diff --git a/packages/cli/src/modules/translations/commands/import.ts b/packages/cli/src/modules/translations/commands/import.ts index 155724dd8c..0e27321da5 100644 --- a/packages/cli/src/modules/translations/commands/import.ts +++ b/packages/cli/src/modules/translations/commands/import.ts @@ -28,7 +28,7 @@ import { createMessagePathParser, formatMessagePath, } from '../lib/messageFilePath'; -import type { CommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '../../../wiring/types'; interface ManifestRefEntry { package: string; @@ -41,7 +41,7 @@ interface Manifest { refs: Record; } -export default async ({ args, info }: CommandContext) => { +export default async ({ args, info }: CliCommandContext) => { const { flags: { input, output }, } = cli( diff --git a/packages/cli/src/wiring/CommandGraph.ts b/packages/cli/src/wiring/CommandGraph.ts index d64d14b41c..b3db5d68bb 100644 --- a/packages/cli/src/wiring/CommandGraph.ts +++ b/packages/cli/src/wiring/CommandGraph.ts @@ -18,7 +18,7 @@ import { OpaqueCommandTreeNode, OpaqueCommandLeafNode, } from '@internal/cli'; -import { BackstageCommand } from './types'; +import { CliCommand } from './types'; /** * A sparse graph of commands. @@ -30,7 +30,7 @@ export class CommandGraph { * Adds a command to the graph. The graph is sparse, so we use the path to determine the nodes * to traverse. Only leaf nodes should have a command/action. */ - add(command: BackstageCommand) { + add(command: CliCommand) { const path = command.path; let current = this.graph; for (let i = 0; i < path.length - 1; i++) { @@ -79,7 +79,7 @@ export class CommandGraph { /** * Given a path, try to find a command that matches it. */ - find(path: string[]): BackstageCommand | undefined { + find(path: string[]): CliCommand | undefined { let current = this.graph; for (let i = 0; i < path.length - 1; i++) { const name = path[i]; diff --git a/packages/cli/src/wiring/CommandRegistry.ts b/packages/cli/src/wiring/CommandRegistry.ts index 9e8ff9646c..c3c1f1956d 100644 --- a/packages/cli/src/wiring/CommandRegistry.ts +++ b/packages/cli/src/wiring/CommandRegistry.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { CommandGraph } from './CommandGraph'; -import { BackstageCommand } from './types'; +import { CliCommand } from './types'; export class CommandRegistry { private graph: CommandGraph; @@ -22,7 +22,7 @@ export class CommandRegistry { this.graph = graph; } - addCommand(command: BackstageCommand) { + addCommand(command: CliCommand) { this.graph.add(command); } } diff --git a/packages/cli/src/wiring/types.ts b/packages/cli/src/wiring/types.ts index 04eedfbd0d..f927645340 100644 --- a/packages/cli/src/wiring/types.ts +++ b/packages/cli/src/wiring/types.ts @@ -15,7 +15,7 @@ */ export type { - CommandContext, - BackstageCommand, + CliCommandContext, + CliCommand, CliPlugin, } from '@backstage/cli-node'; From 18012b5802e36527960537ffbb2d0c35217c1f67 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Mar 2026 07:54:28 +0100 Subject: [PATCH 10/45] Rename CliPlugin to CliModule and cli-plugin role to cli-module Rename createCliPlugin to createCliModule, CliPlugin to CliModule, and the cli-plugin package role to cli-module to better distinguish CLI modules from other plugin types. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/add-cli-plugin-role.md | 2 +- .changeset/cli-node-add-cli-plugin.md | 2 +- .changeset/cli-support-cli-plugin-role.md | 2 +- .changeset/cli-use-cli-plugin-api.md | 2 +- ...ternalCliPlugin.ts => InternalCliModule.ts} | 8 ++++---- packages/cli-internal/src/index.ts | 2 +- packages/cli-node/report.api.md | 10 +++++----- .../createCliModule.ts} | 14 +++++++------- .../src/{cli-plugin => cli-module}/index.ts | 4 ++-- .../src/{cli-plugin => cli-module}/types.ts | 6 +++--- packages/cli-node/src/index.ts | 2 +- packages/cli-node/src/roles/PackageRoles.ts | 2 +- packages/cli-node/src/roles/types.ts | 2 +- packages/cli/config/eslint-factory.js | 2 +- packages/cli/config/jest.js | 2 +- packages/cli/src/modules/auth/index.ts | 4 ++-- packages/cli/src/modules/build/index.ts | 4 ++-- .../modules/build/lib/typeDistProject.test.ts | 2 +- packages/cli/src/modules/config/index.ts | 4 ++-- .../cli/src/modules/create-github-app/index.ts | 4 ++-- packages/cli/src/modules/info/index.ts | 4 ++-- packages/cli/src/modules/lint/index.ts | 4 ++-- .../modules/maintenance/commands/repo/fix.ts | 4 ++-- packages/cli/src/modules/maintenance/index.ts | 4 ++-- .../modules/migrate/commands/packageScripts.ts | 2 +- packages/cli/src/modules/migrate/index.ts | 4 ++-- packages/cli/src/modules/new/index.ts | 4 ++-- packages/cli/src/modules/test/index.ts | 4 ++-- packages/cli/src/modules/translations/index.ts | 4 ++-- packages/cli/src/wiring/CliInitializer.test.ts | 18 +++++++++--------- packages/cli/src/wiring/CliInitializer.ts | 18 +++++++++--------- packages/cli/src/wiring/factory.ts | 2 +- packages/cli/src/wiring/types.ts | 2 +- 33 files changed, 77 insertions(+), 77 deletions(-) rename packages/cli-internal/src/{InternalCliPlugin.ts => InternalCliModule.ts} (83%) rename packages/cli-node/src/{cli-plugin/createCliPlugin.ts => cli-module/createCliModule.ts} (86%) rename packages/cli-node/src/{cli-plugin => cli-module}/index.ts (84%) rename packages/cli-node/src/{cli-plugin => cli-module}/types.ts (96%) diff --git a/.changeset/add-cli-plugin-role.md b/.changeset/add-cli-plugin-role.md index b31c631762..1f09a08ade 100644 --- a/.changeset/add-cli-plugin-role.md +++ b/.changeset/add-cli-plugin-role.md @@ -2,4 +2,4 @@ '@backstage/cli-node': patch --- -Added a new `cli-plugin` package role for packages that provide CLI plugin extensions. +Added a new `cli-module` package role for packages that provide CLI plugin extensions. diff --git a/.changeset/cli-node-add-cli-plugin.md b/.changeset/cli-node-add-cli-plugin.md index b5a26979a9..2a6a5f20bc 100644 --- a/.changeset/cli-node-add-cli-plugin.md +++ b/.changeset/cli-node-add-cli-plugin.md @@ -2,4 +2,4 @@ '@backstage/cli-node': minor --- -Added `createCliPlugin` API and related types for building Backstage CLI plugins. +Added `createCliModule` API and related types for building Backstage CLI plugins. diff --git a/.changeset/cli-support-cli-plugin-role.md b/.changeset/cli-support-cli-plugin-role.md index d56c30db78..b336f7f551 100644 --- a/.changeset/cli-support-cli-plugin-role.md +++ b/.changeset/cli-support-cli-plugin-role.md @@ -2,4 +2,4 @@ '@backstage/cli': patch --- -Added support for the new `cli-plugin` package role in the build system, ESLint configuration, Jest configuration, and maintenance commands. +Added support for the new `cli-module` package role in the build system, ESLint configuration, Jest configuration, and maintenance commands. diff --git a/.changeset/cli-use-cli-plugin-api.md b/.changeset/cli-use-cli-plugin-api.md index cf7f7f12b5..c155483c10 100644 --- a/.changeset/cli-use-cli-plugin-api.md +++ b/.changeset/cli-use-cli-plugin-api.md @@ -2,4 +2,4 @@ '@backstage/cli': patch --- -Migrated CLI plugin modules to use `createCliPlugin` from `@backstage/cli-node`. +Migrated CLI plugin modules to use `createCliModule` from `@backstage/cli-node`. diff --git a/packages/cli-internal/src/InternalCliPlugin.ts b/packages/cli-internal/src/InternalCliModule.ts similarity index 83% rename from packages/cli-internal/src/InternalCliPlugin.ts rename to packages/cli-internal/src/InternalCliModule.ts index 4491e5d7c1..213e309371 100644 --- a/packages/cli-internal/src/InternalCliPlugin.ts +++ b/packages/cli-internal/src/InternalCliModule.ts @@ -14,17 +14,17 @@ * limitations under the License. */ -import { CliCommand, CliPlugin } from '@backstage/cli-node'; +import { CliCommand, CliModule } from '@backstage/cli-node'; import { OpaqueType } from '@internal/opaque'; -export const OpaqueCliPlugin = OpaqueType.create<{ - public: CliPlugin; +export const OpaqueCliModule = OpaqueType.create<{ + public: CliModule; versions: { readonly version: 'v1'; readonly packageName: string; readonly commands: Promise>; }; }>({ - type: '@backstage/CliPlugin', + type: '@backstage/CliModule', versions: ['v1'], }); diff --git a/packages/cli-internal/src/index.ts b/packages/cli-internal/src/index.ts index 578333ee96..68b5affe64 100644 --- a/packages/cli-internal/src/index.ts +++ b/packages/cli-internal/src/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export { OpaqueCliPlugin } from './InternalCliPlugin'; +export { OpaqueCliModule } from './InternalCliModule'; export type { CommandNode, CommandTreeNode, diff --git a/packages/cli-node/report.api.md b/packages/cli-node/report.api.md index d2d4db856d..b979fff0b0 100644 --- a/packages/cli-node/report.api.md +++ b/packages/cli-node/report.api.md @@ -111,9 +111,9 @@ export interface CliCommandContext { } // @public -export interface CliPlugin { +export interface CliModule { // (undocumented) - readonly $$type: '@backstage/CliPlugin'; + readonly $$type: '@backstage/CliModule'; } // @public @@ -124,14 +124,14 @@ export type ConcurrentTasksOptions = { }; // @public -export function createCliPlugin(options: { +export function createCliModule(options: { packageJson: { name: string; }; init: (registry: { addCommand: (command: CliCommand) => void; }) => Promise; -}): CliPlugin; +}): CliModule; // @public export class GitUtils { @@ -227,7 +227,7 @@ export type PackageRole = | 'frontend' | 'backend' | 'cli' - | 'cli-plugin' + | 'cli-module' | 'web-library' | 'node-library' | 'common-library' diff --git a/packages/cli-node/src/cli-plugin/createCliPlugin.ts b/packages/cli-node/src/cli-module/createCliModule.ts similarity index 86% rename from packages/cli-node/src/cli-plugin/createCliPlugin.ts rename to packages/cli-node/src/cli-module/createCliModule.ts index dcb79e0b3f..89ed21876f 100644 --- a/packages/cli-node/src/cli-plugin/createCliPlugin.ts +++ b/packages/cli-node/src/cli-module/createCliModule.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { OpaqueCliPlugin } from '@internal/cli'; -import { CliCommand, CliPlugin } from './types'; +import { OpaqueCliModule } from '@internal/cli'; +import { CliCommand, CliModule } from './types'; /** * Creates a new CLI plugin that provides commands to the Backstage CLI. @@ -26,10 +26,10 @@ import { CliCommand, CliPlugin } from './types'; * * @example * ``` - * import { createCliPlugin } from '@backstage/cli-node'; + * import { createCliModule } from '@backstage/cli-node'; * import packageJson from '../package.json'; * - * export default createCliPlugin({ + * export default createCliModule({ * packageJson, * init: async reg => { * reg.addCommand({ @@ -43,7 +43,7 @@ import { CliCommand, CliPlugin } from './types'; * * @public */ -export function createCliPlugin(options: { +export function createCliModule(options: { /** The `package.json` contents of the plugin package, used to identify the plugin. */ packageJson: { name: string }; /** @@ -54,13 +54,13 @@ export function createCliPlugin(options: { /** Registers a new command with the CLI. */ addCommand: (command: CliCommand) => void; }) => Promise; -}): CliPlugin { +}): CliModule { const commands: CliCommand[] = []; const commandsPromise = options .init({ addCommand: command => commands.push(command) }) .then(() => commands); - return OpaqueCliPlugin.createInstance('v1', { + return OpaqueCliModule.createInstance('v1', { packageName: options.packageJson.name, commands: commandsPromise, }); diff --git a/packages/cli-node/src/cli-plugin/index.ts b/packages/cli-node/src/cli-module/index.ts similarity index 84% rename from packages/cli-node/src/cli-plugin/index.ts rename to packages/cli-node/src/cli-module/index.ts index df8b340c50..646073a815 100644 --- a/packages/cli-node/src/cli-plugin/index.ts +++ b/packages/cli-node/src/cli-module/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { createCliPlugin } from './createCliPlugin'; -export type { CliCommand, CliCommandContext, CliPlugin } from './types'; +export { createCliModule } from './createCliModule'; +export type { CliCommand, CliCommandContext, CliModule } from './types'; diff --git a/packages/cli-node/src/cli-plugin/types.ts b/packages/cli-node/src/cli-module/types.ts similarity index 96% rename from packages/cli-node/src/cli-plugin/types.ts rename to packages/cli-node/src/cli-module/types.ts index 21dac09eb9..3db290f89f 100644 --- a/packages/cli-node/src/cli-plugin/types.ts +++ b/packages/cli-node/src/cli-module/types.ts @@ -109,10 +109,10 @@ export interface CliCommand { /** * An opaque representation of a Backstage CLI plugin, created - * using {@link createCliPlugin}. + * using {@link createCliModule}. * * @public */ -export interface CliPlugin { - readonly $$type: '@backstage/CliPlugin'; +export interface CliModule { + readonly $$type: '@backstage/CliModule'; } diff --git a/packages/cli-node/src/index.ts b/packages/cli-node/src/index.ts index 7c18070bbe..8831753a82 100644 --- a/packages/cli-node/src/index.ts +++ b/packages/cli-node/src/index.ts @@ -21,7 +21,7 @@ */ export * from './cache'; -export * from './cli-plugin'; +export * from './cli-module'; export * from './concurrency'; export * from './git'; export * from './monorepo'; diff --git a/packages/cli-node/src/roles/PackageRoles.ts b/packages/cli-node/src/roles/PackageRoles.ts index b0ee82af84..7761b0d4cc 100644 --- a/packages/cli-node/src/roles/PackageRoles.ts +++ b/packages/cli-node/src/roles/PackageRoles.ts @@ -34,7 +34,7 @@ const packageRoleInfos: PackageRoleInfo[] = [ output: ['cjs'], }, { - role: 'cli-plugin', + role: 'cli-module', platform: 'node', output: ['types', 'cjs'], }, diff --git a/packages/cli-node/src/roles/types.ts b/packages/cli-node/src/roles/types.ts index 29e5fbb5d6..d0eaedbd02 100644 --- a/packages/cli-node/src/roles/types.ts +++ b/packages/cli-node/src/roles/types.ts @@ -23,7 +23,7 @@ export type PackageRole = | 'frontend' | 'backend' | 'cli' - | 'cli-plugin' + | 'cli-module' | 'web-library' | 'node-library' | 'common-library' diff --git a/packages/cli/config/eslint-factory.js b/packages/cli/config/eslint-factory.js index db547f9b15..4e51803802 100644 --- a/packages/cli/config/eslint-factory.js +++ b/packages/cli/config/eslint-factory.js @@ -269,7 +269,7 @@ function createConfigForRole(dir, role, extraConfig = {}) { }); case 'cli': - case 'cli-plugin': + case 'cli-module': case 'node-library': case 'backend': case 'backend-plugin': diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js index 07f92002ae..8a88483d42 100644 --- a/packages/cli/config/jest.js +++ b/packages/cli/config/jest.js @@ -38,7 +38,7 @@ const FRONTEND_ROLES = [ const NODE_ROLES = [ 'backend', 'cli', - 'cli-plugin', + 'cli-module', 'node-library', 'backend-plugin', 'backend-plugin-module', diff --git a/packages/cli/src/modules/auth/index.ts b/packages/cli/src/modules/auth/index.ts index 6ce849a9b9..25876bbece 100644 --- a/packages/cli/src/modules/auth/index.ts +++ b/packages/cli/src/modules/auth/index.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { createCliPlugin } from '../../wiring/factory'; +import { createCliModule } from '../../wiring/factory'; import packageJson from '../../../package.json'; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/build/index.ts b/packages/cli/src/modules/build/index.ts index e3c04e6325..ac389c6a68 100644 --- a/packages/cli/src/modules/build/index.ts +++ b/packages/cli/src/modules/build/index.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import packageJson from '../../../package.json'; -export const buildPlugin = createCliPlugin({ +export const buildPlugin = createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/build/lib/typeDistProject.test.ts b/packages/cli/src/modules/build/lib/typeDistProject.test.ts index c773c505be..9d14bccc15 100644 --- a/packages/cli/src/modules/build/lib/typeDistProject.test.ts +++ b/packages/cli/src/modules/build/lib/typeDistProject.test.ts @@ -33,7 +33,7 @@ describe('typeDistProject', () => { frontend: false, backend: false, cli: false, - 'cli-plugin': false, + 'cli-module': false, 'common-library': false, }; diff --git a/packages/cli/src/modules/config/index.ts b/packages/cli/src/modules/config/index.ts index e2ddec3678..89a7d90111 100644 --- a/packages/cli/src/modules/config/index.ts +++ b/packages/cli/src/modules/config/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import packageJson from '../../../package.json'; export const configOption = [ @@ -23,7 +23,7 @@ export const configOption = [ Array(), ] as const; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/create-github-app/index.ts b/packages/cli/src/modules/create-github-app/index.ts index 2171f2ca2e..04786cbbdb 100644 --- a/packages/cli/src/modules/create-github-app/index.ts +++ b/packages/cli/src/modules/create-github-app/index.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import packageJson from '../../../package.json'; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/info/index.ts b/packages/cli/src/modules/info/index.ts index b1fa885f03..c4a839ff12 100644 --- a/packages/cli/src/modules/info/index.ts +++ b/packages/cli/src/modules/info/index.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import packageJson from '../../../package.json'; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/lint/index.ts b/packages/cli/src/modules/lint/index.ts index 7da72679d4..71961a147f 100644 --- a/packages/cli/src/modules/lint/index.ts +++ b/packages/cli/src/modules/lint/index.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import packageJson from '../../../package.json'; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/maintenance/commands/repo/fix.ts b/packages/cli/src/modules/maintenance/commands/repo/fix.ts index d3e0759afc..147779443d 100644 --- a/packages/cli/src/modules/maintenance/commands/repo/fix.ts +++ b/packages/cli/src/modules/maintenance/commands/repo/fix.ts @@ -298,7 +298,7 @@ export function fixPluginId(pkg: FixablePackage) { role === 'backend' || role === 'frontend' || role === 'cli' || - role === 'cli-plugin' + role === 'cli-module' ) { return; } @@ -385,7 +385,7 @@ export function fixPluginPackages( role === 'backend' || role === 'frontend' || role === 'cli' || - role === 'cli-plugin' + role === 'cli-module' ) { return; } diff --git a/packages/cli/src/modules/maintenance/index.ts b/packages/cli/src/modules/maintenance/index.ts index cf6cf00b2c..315d222448 100644 --- a/packages/cli/src/modules/maintenance/index.ts +++ b/packages/cli/src/modules/maintenance/index.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import packageJson from '../../../package.json'; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/migrate/commands/packageScripts.ts b/packages/cli/src/modules/migrate/commands/packageScripts.ts index 80810f31fc..b9bc9d6656 100644 --- a/packages/cli/src/modules/migrate/commands/packageScripts.ts +++ b/packages/cli/src/modules/migrate/commands/packageScripts.ts @@ -22,7 +22,7 @@ import type { CliCommandContext } from '../../../wiring/types'; const configArgPattern = /--config[=\s][^\s$]+/; -const noStartRoles: PackageRole[] = ['cli', 'cli-plugin', 'common-library']; +const noStartRoles: PackageRole[] = ['cli', 'cli-module', 'common-library']; export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); diff --git a/packages/cli/src/modules/migrate/index.ts b/packages/cli/src/modules/migrate/index.ts index 16cf45d244..ca77f678a4 100644 --- a/packages/cli/src/modules/migrate/index.ts +++ b/packages/cli/src/modules/migrate/index.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import packageJson from '../../../package.json'; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/new/index.ts b/packages/cli/src/modules/new/index.ts index 9ceb50e272..2a08a71e97 100644 --- a/packages/cli/src/modules/new/index.ts +++ b/packages/cli/src/modules/new/index.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import { NotImplementedError } from '@backstage/errors'; import packageJson from '../../../package.json'; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/test/index.ts b/packages/cli/src/modules/test/index.ts index 07eabbf3f7..f10e13828f 100644 --- a/packages/cli/src/modules/test/index.ts +++ b/packages/cli/src/modules/test/index.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import packageJson from '../../../package.json'; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/modules/translations/index.ts b/packages/cli/src/modules/translations/index.ts index 1903d87684..7654c2e0b6 100644 --- a/packages/cli/src/modules/translations/index.ts +++ b/packages/cli/src/modules/translations/index.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createCliPlugin } from '@backstage/cli-node'; +import { createCliModule } from '@backstage/cli-node'; import packageJson from '../../../package.json'; -export default createCliPlugin({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ diff --git a/packages/cli/src/wiring/CliInitializer.test.ts b/packages/cli/src/wiring/CliInitializer.test.ts index c5d304db91..b5ac9cfaaa 100644 --- a/packages/cli/src/wiring/CliInitializer.test.ts +++ b/packages/cli/src/wiring/CliInitializer.test.ts @@ -15,7 +15,7 @@ */ import { CliInitializer } from './CliInitializer'; -import { createCliPlugin } from './factory'; +import { createCliModule } from './factory'; process.exit = jest.fn() as any; @@ -28,7 +28,7 @@ describe('CliInitializer', () => { process.argv = ['node', 'cli', 'test']; const initializer = new CliInitializer(); initializer.add( - createCliPlugin({ + createCliModule({ packageJson: { name: '@backstage/test' }, init: async reg => reg.addCommand({ @@ -50,7 +50,7 @@ describe('CliInitializer', () => { process.argv = ['node', 'cli', 'test', '[positional]', '']; const initializer = new CliInitializer(); initializer.add( - createCliPlugin({ + createCliModule({ packageJson: { name: '@backstage/test' }, init: async reg => reg.addCommand({ @@ -72,7 +72,7 @@ describe('CliInitializer', () => { process.argv = ['node', 'cli', 'test', '--verbose']; const initializer = new CliInitializer(); initializer.add( - createCliPlugin({ + createCliModule({ packageJson: { name: '@backstage/test' }, init: async reg => reg.addCommand({ @@ -97,7 +97,7 @@ describe('CliInitializer', () => { process.argv = ['node', 'cli', 'secret']; const initializer = new CliInitializer(); initializer.add( - createCliPlugin({ + createCliModule({ packageJson: { name: '@backstage/test' }, init: async reg => { reg.addCommand({ @@ -124,7 +124,7 @@ describe('CliInitializer', () => { const writeSpy = jest.spyOn(process.stdout, 'write'); const initializer2 = new CliInitializer(); initializer2.add( - createCliPlugin({ + createCliModule({ packageJson: { name: '@backstage/test' }, init: async reg => { reg.addCommand({ @@ -152,7 +152,7 @@ describe('CliInitializer', () => { const writeSpy = jest.spyOn(process.stdout, 'write'); const initializer = new CliInitializer(); initializer.add( - createCliPlugin({ + createCliModule({ packageJson: { name: '@backstage/test' }, init: async reg => { reg.addCommand({ @@ -187,7 +187,7 @@ describe('CliInitializer', () => { const writeSpy = jest.spyOn(process.stdout, 'write'); const initializer = new CliInitializer(); initializer.add( - createCliPlugin({ + createCliModule({ packageJson: { name: '@backstage/test' }, init: async reg => { reg.addCommand({ @@ -223,7 +223,7 @@ describe('CliInitializer', () => { ]; const initializer = new CliInitializer(); initializer.add( - createCliPlugin({ + createCliModule({ packageJson: { name: '@backstage/test' }, init: async reg => reg.addCommand({ diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index 37156641ee..a09adbbc89 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -16,12 +16,12 @@ import { CommandGraph } from './CommandGraph'; import { - OpaqueCliPlugin, + OpaqueCliModule, OpaqueCommandTreeNode, OpaqueCommandLeafNode, } from '@internal/cli'; import type { CommandNode } from '@internal/cli'; -import type { CliPlugin } from '@backstage/cli-node'; +import type { CliModule } from '@backstage/cli-node'; import { CommandRegistry } from './CommandRegistry'; import { Command } from 'commander'; import { version } from './version'; @@ -39,12 +39,12 @@ function isNodeHidden(node: CommandNode): boolean { return children.every(child => isNodeHidden(child)); } -type UninitializedFeature = CliPlugin | Promise<{ default: CliPlugin }>; +type UninitializedFeature = CliModule | Promise<{ default: CliModule }>; export class CliInitializer { private graph = new CommandGraph(); private commandRegistry = new CommandRegistry(this.graph); - #uninitiazedFeatures: Promise[] = []; + #uninitiazedFeatures: Promise[] = []; add(feature: UninitializedFeature) { if (isPromise(feature)) { @@ -56,9 +56,9 @@ export class CliInitializer { } } - async #register(feature: CliPlugin) { - if (OpaqueCliPlugin.isType(feature)) { - const internal = OpaqueCliPlugin.toInternal(feature); + async #register(feature: CliModule) { + if (OpaqueCliModule.isType(feature)) { + const internal = OpaqueCliModule.toInternal(feature); for (const command of await internal.commands) { this.commandRegistry.addCommand(command); } @@ -186,8 +186,8 @@ export class CliInitializer { /** @internal */ export function unwrapFeature( - feature: CliPlugin | { default: CliPlugin }, -): CliPlugin { + feature: CliModule | { default: CliModule }, +): CliModule { if ('$$type' in feature) { return feature; } diff --git a/packages/cli/src/wiring/factory.ts b/packages/cli/src/wiring/factory.ts index e840e694c6..f8f04715c3 100644 --- a/packages/cli/src/wiring/factory.ts +++ b/packages/cli/src/wiring/factory.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { createCliPlugin } from '@backstage/cli-node'; +export { createCliModule } from '@backstage/cli-node'; diff --git a/packages/cli/src/wiring/types.ts b/packages/cli/src/wiring/types.ts index f927645340..7a8a009a60 100644 --- a/packages/cli/src/wiring/types.ts +++ b/packages/cli/src/wiring/types.ts @@ -17,5 +17,5 @@ export type { CliCommandContext, CliCommand, - CliPlugin, + CliModule, } from '@backstage/cli-node'; From a151ad0814ae75904398a9555cd5600a1b311982 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Mar 2026 13:43:02 +0100 Subject: [PATCH 11/45] Split CLI modules into separate packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract each CLI module from packages/cli/src/modules/ into its own package under packages/cli-module-*. This enables independent versioning and clearer dependency boundaries for each CLI capability. Module mapping: - auth → @backstage/cli-module-auth - build → @backstage/cli-module-build - config → @backstage/cli-module-config - create-github-app → @backstage/cli-module-create-github-app - info → @backstage/cli-module-info - lint → @backstage/cli-module-lint - maintenance → @backstage/cli-module-maintenance - migrate → @backstage/cli-module-migrate - new → @backstage/cli-module-new - test → @backstage/cli-module-test-jest - translations → @backstage/cli-module-translations Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-auth/.eslintrc.js | 1 + packages/cli-module-auth/catalog-info.yaml | 10 + packages/cli-module-auth/package.json | 51 ++ .../src}/commands/list.ts | 2 +- .../src}/commands/login.ts | 2 +- .../src}/commands/logout.ts | 2 +- .../src}/commands/printToken.ts | 2 +- .../src}/commands/select.ts | 2 +- .../src}/commands/show.ts | 2 +- .../auth => cli-module-auth/src}/index.ts | 4 +- .../src}/lib/auth.test.ts | 0 .../auth => cli-module-auth/src}/lib/auth.ts | 0 .../src}/lib/http.test.ts | 0 .../auth => cli-module-auth/src}/lib/http.ts | 0 .../src}/lib/localServer.test.ts | 0 .../src}/lib/localServer.ts | 0 .../src}/lib/pkce.test.ts | 0 .../auth => cli-module-auth/src}/lib/pkce.ts | 0 .../src}/lib/prompt.test.ts | 0 .../src}/lib/prompt.ts | 0 .../src}/lib/secretStore.test.ts | 0 .../src}/lib/secretStore.ts | 0 .../src}/lib/storage.test.ts | 0 .../src}/lib/storage.ts | 0 packages/cli-module-build/.eslintrc.js | 1 + packages/cli-module-build/catalog-info.yaml | 10 + packages/cli-module-build/package.json | 92 ++ .../src}/commands/buildWorkspace.ts | 2 +- .../src}/commands/package/build/command.ts | 2 +- .../src}/commands/package/build/index.ts | 0 .../src}/commands/package/clean.ts | 2 +- .../src}/commands/package/postpack.ts | 2 +- .../src}/commands/package/prepack.ts | 2 +- .../src}/commands/package/start/command.ts | 2 +- .../src}/commands/package/start/index.ts | 0 .../package/start/resolveLinkedWorkspace.ts | 0 .../commands/package/start/startBackend.ts | 0 .../commands/package/start/startFrontend.ts | 0 .../package/start/startPackage.test.ts | 0 .../commands/package/start/startPackage.ts | 0 .../src}/commands/repo/build.ts | 2 +- .../src}/commands/repo/clean.ts | 2 +- .../src}/commands/repo/start.test.ts | 0 .../src}/commands/repo/start.ts | 2 +- .../build => cli-module-build/src}/index.ts | 2 +- .../__testUtils__/createFeatureEnvironment.ts | 0 .../src}/lib/buildBackend.ts | 0 .../src}/lib/buildFrontend.ts | 0 .../src}/lib/builder/config.test.ts | 0 .../src}/lib/builder/config.ts | 0 .../src}/lib/builder/index.ts | 0 .../src}/lib/builder/packager.test.ts | 0 .../src}/lib/builder/packager.ts | 0 .../src}/lib/builder/plugins.test.ts | 0 .../src}/lib/builder/plugins.ts | 0 .../src}/lib/builder/types.ts | 0 .../ConfigInjectingHtmlWebpackPlugin.ts | 0 .../src}/lib/bundler/bundle.ts | 0 .../src}/lib/bundler/config.ts | 2 +- .../src}/lib/bundler/hasReactDomClient.ts | 0 .../src}/lib/bundler/index.ts | 0 .../src}/lib/bundler/linkWorkspaces.ts | 0 .../src}/lib/bundler/moduleFederation.test.ts | 0 .../src}/lib/bundler/moduleFederation.ts | 0 .../src}/lib/bundler/optimization.ts | 0 .../src}/lib/bundler/packageDetection.ts | 0 .../src}/lib/bundler/paths.ts | 6 +- .../src}/lib/bundler/server.ts | 0 .../src}/lib/bundler/transforms.ts | 0 .../src}/lib/bundler/types.ts | 0 .../src}/lib/config.ts | 0 .../src}/lib/entryPoints.ts | 0 .../src}/lib/ipc/IpcServer.ts | 0 .../src}/lib/ipc/ServerDataStore.ts | 0 .../src}/lib/ipc/index.ts | 0 .../src}/lib/optionsParser.ts | 0 .../src}/lib/packager/createDistWorkspace.ts | 11 +- .../src}/lib/packager/index.ts | 0 .../src}/lib/packager/productionPack.ts | 0 .../src}/lib/publishing.ts | 0 .../src}/lib/role.test.ts | 0 .../src}/lib/role.ts | 0 .../src}/lib/runner/index.ts | 0 .../src}/lib/runner/runBackend.test.ts | 0 .../src}/lib/runner/runBackend.ts | 0 .../src}/lib/typeDistProject.test.ts | 0 .../src}/lib/typeDistProject.ts | 0 .../src}/lib/urls.test.ts | 0 .../src}/lib/urls.ts | 0 .../tests/transforms/__fixtures__/.gitignore | 0 .../node_modules/dep-commonjs/a-default.js | 0 .../node_modules/dep-commonjs/a-named.js | 0 .../node_modules/dep-commonjs/b-default.mjs | 0 .../node_modules/dep-commonjs/b-named.mjs | 0 .../node_modules/dep-commonjs/c-default.cjs | 0 .../node_modules/dep-commonjs/c-named.cjs | 0 .../node_modules/dep-commonjs/main.d.ts | 0 .../node_modules/dep-commonjs/main.js | 0 .../node_modules/dep-commonjs/package.json | 0 .../node_modules/dep-default/a-default.js | 0 .../node_modules/dep-default/a-named.js | 0 .../node_modules/dep-default/b-default.mjs | 0 .../node_modules/dep-default/b-named.mjs | 0 .../node_modules/dep-default/c-default.cjs | 0 .../node_modules/dep-default/c-named.cjs | 0 .../node_modules/dep-default/main.d.ts | 0 .../node_modules/dep-default/main.js | 0 .../node_modules/dep-default/package.json | 0 .../node_modules/dep-module/a-default.js | 0 .../node_modules/dep-module/a-named.js | 0 .../node_modules/dep-module/b-default.mjs | 0 .../node_modules/dep-module/b-named.mjs | 0 .../node_modules/dep-module/c-default.cjs | 0 .../node_modules/dep-module/c-named.cjs | 0 .../node_modules/dep-module/main.d.ts | 0 .../node_modules/dep-module/main.js | 0 .../node_modules/dep-module/package.json | 0 .../__fixtures__/pkg-commonjs/a-default.ts | 0 .../__fixtures__/pkg-commonjs/a-named.ts | 0 .../__fixtures__/pkg-commonjs/b-default.mts | 0 .../__fixtures__/pkg-commonjs/b-named.mts | 0 .../__fixtures__/pkg-commonjs/c-default.cts | 0 .../__fixtures__/pkg-commonjs/c-named.cts | 0 .../__fixtures__/pkg-commonjs/main.ts | 0 .../__fixtures__/pkg-commonjs/package.json | 0 .../__fixtures__/pkg-commonjs/print.ts | 0 .../__fixtures__/pkg-default/a-default.ts | 0 .../__fixtures__/pkg-default/a-named.ts | 0 .../__fixtures__/pkg-default/b-default.mts | 0 .../__fixtures__/pkg-default/b-named.mts | 0 .../__fixtures__/pkg-default/c-default.cts | 0 .../__fixtures__/pkg-default/c-named.cts | 0 .../__fixtures__/pkg-default/main.ts | 0 .../__fixtures__/pkg-default/package.json | 0 .../__fixtures__/pkg-default/print.ts | 0 .../pkg-module/a-default-explicit.mts | 0 .../__fixtures__/pkg-module/a-default.ts | 0 .../pkg-module/a-named-explicit.mts | 0 .../__fixtures__/pkg-module/a-named.ts | 0 .../__fixtures__/pkg-module/b-default.mts | 0 .../__fixtures__/pkg-module/b-named.mts | 0 .../__fixtures__/pkg-module/c-default.cts | 0 .../__fixtures__/pkg-module/c-named.cts | 0 .../__fixtures__/pkg-module/main-explicit.mts | 0 .../__fixtures__/pkg-module/main.ts | 0 .../__fixtures__/pkg-module/package.json | 0 .../__fixtures__/pkg-module/print.ts | 0 .../src}/tests/transforms/transforms.test.ts | 0 packages/cli-module-config/.eslintrc.js | 1 + packages/cli-module-config/catalog-info.yaml | 10 + packages/cli-module-config/package.json | 50 ++ .../src}/commands/docs.ts | 2 +- .../src}/commands/print.ts | 2 +- .../src}/commands/schema.ts | 2 +- .../src}/commands/validate.ts | 2 +- .../config => cli-module-config/src}/index.ts | 2 +- .../src}/lib/config.ts | 0 .../cli-module-create-github-app/.eslintrc.js | 1 + .../catalog-info.yaml | 10 + .../cli-module-create-github-app/package.json | 50 ++ .../GithubCreateAppServer.ts | 0 .../src}/commands/create-github-app/index.ts | 2 +- .../src}/index.ts | 2 +- packages/cli-module-info/.eslintrc.js | 1 + packages/cli-module-info/catalog-info.yaml | 10 + packages/cli-module-info/package.json | 44 + .../src}/commands/info.ts | 6 +- .../info => cli-module-info/src}/index.ts | 2 +- packages/cli-module-lint/.eslintrc.js | 1 + packages/cli-module-lint/catalog-info.yaml | 10 + packages/cli-module-lint/package.json | 48 ++ .../src}/commands/package/lint.ts | 2 +- .../src}/commands/repo/lint.ts | 2 +- .../lint => cli-module-lint/src}/index.ts | 2 +- .../src}/lib/optionsParser.ts | 0 packages/cli-module-maintenance/.eslintrc.js | 1 + .../cli-module-maintenance/catalog-info.yaml | 10 + packages/cli-module-maintenance/package.json | 45 + .../src}/commands/repo/fix.ts | 2 +- .../src}/commands/repo/list-deprecations.ts | 2 +- .../src}/index.ts | 2 +- packages/cli-module-migrate/.eslintrc.js | 1 + packages/cli-module-migrate/catalog-info.yaml | 10 + packages/cli-module-migrate/package.json | 48 ++ .../src}/commands/packageExports.ts | 2 +- .../src}/commands/packageLintConfigs.ts | 2 +- .../src}/commands/packageRole.ts | 2 +- .../src}/commands/packageScripts.ts | 2 +- .../src}/commands/reactRouterDeps.ts | 2 +- .../src}/commands/versions/bump.test.ts | 0 .../src}/commands/versions/bump.ts | 2 +- .../src}/commands/versions/migrate.test.ts | 0 .../src}/commands/versions/migrate.ts | 2 +- .../src}/index.ts | 2 +- .../src}/lib/utils.ts | 0 .../src}/lib/versioning/packages.test.ts | 0 .../src}/lib/versioning/packages.ts | 0 .../src}/lib/versioning/yarn.ts | 0 packages/cli-module-new/.eslintrc.js | 1 + packages/cli-module-new/catalog-info.yaml | 10 + packages/cli-module-new/package.json | 39 + .../src}/commands/new.test.ts | 2 +- .../src}/commands/new.ts | 2 +- .../new => cli-module-new/src}/index.ts | 2 +- .../src}/lib/codeowners/codeowners.test.ts | 0 .../src}/lib/codeowners/codeowners.ts | 0 .../src}/lib/codeowners/index.ts | 0 .../src}/lib/createNewPackage.ts | 0 .../src}/lib/defaultTemplates.ts | 0 .../src}/lib/execution/PortableTemplater.ts | 0 .../lib/execution/executePortableTemplate.ts | 0 .../src}/lib/execution/index.ts | 0 .../src}/lib/execution/installNewPackage.ts | 0 .../execution/writeTemplateContents.test.ts | 0 .../lib/execution/writeTemplateContents.ts | 0 .../collectPortableTemplateInput.test.ts | 0 .../collectPortableTemplateInput.ts | 0 .../src}/lib/preparation/index.ts | 0 .../preparation/loadPortableTemplate.test.ts | 0 .../lib/preparation/loadPortableTemplate.ts | 0 .../loadPortableTemplateConfig.test.ts | 0 .../preparation/loadPortableTemplateConfig.ts | 0 .../preparation/resolvePackageParams.test.ts | 0 .../lib/preparation/resolvePackageParams.ts | 0 .../selectTemplateInteractively.test.ts | 0 .../selectTemplateInteractively.ts | 0 .../new => cli-module-new/src}/lib/tasks.ts | 0 .../new => cli-module-new/src}/lib/types.ts | 0 .../src}/lib/version.test.ts | 0 .../new => cli-module-new/src}/lib/version.ts | 46 +- packages/cli-module-test-jest/.eslintrc.js | 1 + .../cli-module-test-jest/catalog-info.yaml | 10 + packages/cli-module-test-jest/package.json | 39 + .../src}/commands/package/test.ts | 6 +- .../src}/commands/repo/test.test.ts | 0 .../src}/commands/repo/test.ts | 5 +- .../src}/index.ts | 2 +- packages/cli-module-translations/.eslintrc.js | 1 + .../cli-module-translations/catalog-info.yaml | 10 + packages/cli-module-translations/package.json | 39 + .../src}/commands/export.ts | 2 +- .../src}/commands/import.ts | 2 +- .../src}/index.ts | 2 +- .../src}/lib/discoverPackages.ts | 0 .../src}/lib/extractTranslations.test.ts | 0 .../src}/lib/extractTranslations.ts | 0 .../src}/lib/messageFilePath.test.ts | 0 .../src}/lib/messageFilePath.ts | 0 packages/cli/package.json | 11 + packages/cli/src/index.ts | 22 +- yarn.lock | 791 ++++++++++++------ 251 files changed, 1327 insertions(+), 339 deletions(-) create mode 100644 packages/cli-module-auth/.eslintrc.js create mode 100644 packages/cli-module-auth/catalog-info.yaml create mode 100644 packages/cli-module-auth/package.json rename packages/{cli/src/modules/auth => cli-module-auth/src}/commands/list.ts (94%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/commands/login.ts (99%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/commands/logout.ts (97%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/commands/printToken.ts (96%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/commands/select.ts (95%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/commands/show.ts (97%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/index.ts (94%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/auth.test.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/auth.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/http.test.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/http.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/localServer.test.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/localServer.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/pkce.test.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/pkce.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/prompt.test.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/prompt.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/secretStore.test.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/secretStore.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/storage.test.ts (100%) rename packages/{cli/src/modules/auth => cli-module-auth/src}/lib/storage.ts (100%) create mode 100644 packages/cli-module-build/.eslintrc.js create mode 100644 packages/cli-module-build/catalog-info.yaml create mode 100644 packages/cli-module-build/package.json rename packages/{cli/src/modules/build => cli-module-build/src}/commands/buildWorkspace.ts (96%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/build/command.ts (98%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/build/index.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/clean.ts (93%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/postpack.ts (93%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/prepack.ts (95%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/start/command.ts (97%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/start/index.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/start/resolveLinkedWorkspace.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/start/startBackend.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/start/startFrontend.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/start/startPackage.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/package/start/startPackage.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/repo/build.ts (98%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/repo/clean.ts (96%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/repo/start.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/commands/repo/start.ts (99%) rename packages/{cli/src/modules/build => cli-module-build/src}/index.ts (98%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/__testUtils__/createFeatureEnvironment.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/buildBackend.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/buildFrontend.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/builder/config.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/builder/config.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/builder/index.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/builder/packager.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/builder/packager.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/builder/plugins.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/builder/plugins.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/builder/types.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/ConfigInjectingHtmlWebpackPlugin.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/bundle.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/config.ts (99%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/hasReactDomClient.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/index.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/linkWorkspaces.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/moduleFederation.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/moduleFederation.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/optimization.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/packageDetection.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/paths.ts (94%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/server.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/transforms.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/bundler/types.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/config.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/entryPoints.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/ipc/IpcServer.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/ipc/ServerDataStore.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/ipc/index.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/optionsParser.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/packager/createDistWorkspace.ts (98%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/packager/index.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/packager/productionPack.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/publishing.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/role.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/role.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/runner/index.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/runner/runBackend.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/runner/runBackend.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/typeDistProject.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/typeDistProject.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/urls.test.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/lib/urls.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/.gitignore (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-default.js (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-named.js (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-default.mjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-named.mjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-default.cjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-named.cjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.d.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.js (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-commonjs/package.json (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-default/a-default.js (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-default/a-named.js (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-default/b-default.mjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-default/b-named.mjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-default/c-default.cjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-default/c-named.cjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-default/main.d.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-default/main.js (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-default/package.json (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-module/a-default.js (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-module/a-named.js (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-module/b-default.mjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-module/b-named.mjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-module/c-default.cjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-module/c-named.cjs (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-module/main.d.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-module/main.js (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/node_modules/dep-module/package.json (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-commonjs/a-default.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-commonjs/a-named.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-commonjs/b-default.mts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-commonjs/b-named.mts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-commonjs/c-default.cts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-commonjs/c-named.cts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-commonjs/main.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-commonjs/package.json (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-commonjs/print.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-default/a-default.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-default/a-named.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-default/b-default.mts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-default/b-named.mts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-default/c-default.cts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-default/c-named.cts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-default/main.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-default/package.json (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-default/print.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/a-default-explicit.mts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/a-default.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/a-named-explicit.mts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/a-named.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/b-default.mts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/b-named.mts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/c-default.cts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/c-named.cts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/main-explicit.mts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/main.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/package.json (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/__fixtures__/pkg-module/print.ts (100%) rename packages/{cli/src/modules/build => cli-module-build/src}/tests/transforms/transforms.test.ts (100%) create mode 100644 packages/cli-module-config/.eslintrc.js create mode 100644 packages/cli-module-config/catalog-info.yaml create mode 100644 packages/cli-module-config/package.json rename packages/{cli/src/modules/config => cli-module-config/src}/commands/docs.ts (97%) rename packages/{cli/src/modules/config => cli-module-config/src}/commands/print.ts (98%) rename packages/{cli/src/modules/config => cli-module-config/src}/commands/schema.ts (97%) rename packages/{cli/src/modules/config => cli-module-config/src}/commands/validate.ts (96%) rename packages/{cli/src/modules/config => cli-module-config/src}/index.ts (97%) rename packages/{cli/src/modules/config => cli-module-config/src}/lib/config.ts (100%) create mode 100644 packages/cli-module-create-github-app/.eslintrc.js create mode 100644 packages/cli-module-create-github-app/catalog-info.yaml create mode 100644 packages/cli-module-create-github-app/package.json rename packages/{cli/src/modules/create-github-app => cli-module-create-github-app/src}/commands/create-github-app/GithubCreateAppServer.ts (100%) rename packages/{cli/src/modules/create-github-app => cli-module-create-github-app/src}/commands/create-github-app/index.ts (98%) rename packages/{cli/src/modules/create-github-app => cli-module-create-github-app/src}/index.ts (95%) create mode 100644 packages/cli-module-info/.eslintrc.js create mode 100644 packages/cli-module-info/catalog-info.yaml create mode 100644 packages/cli-module-info/package.json rename packages/{cli/src/modules/info => cli-module-info/src}/commands/info.ts (97%) rename packages/{cli/src/modules/info => cli-module-info/src}/index.ts (95%) create mode 100644 packages/cli-module-lint/.eslintrc.js create mode 100644 packages/cli-module-lint/catalog-info.yaml create mode 100644 packages/cli-module-lint/package.json rename packages/{cli/src/modules/lint => cli-module-lint/src}/commands/package/lint.ts (97%) rename packages/{cli/src/modules/lint => cli-module-lint/src}/commands/repo/lint.ts (99%) rename packages/{cli/src/modules/lint => cli-module-lint/src}/index.ts (95%) rename packages/{cli/src/modules/lint => cli-module-lint/src}/lib/optionsParser.ts (100%) create mode 100644 packages/cli-module-maintenance/.eslintrc.js create mode 100644 packages/cli-module-maintenance/catalog-info.yaml create mode 100644 packages/cli-module-maintenance/package.json rename packages/{cli/src/modules/maintenance => cli-module-maintenance/src}/commands/repo/fix.ts (99%) rename packages/{cli/src/modules/maintenance => cli-module-maintenance/src}/commands/repo/list-deprecations.ts (97%) rename packages/{cli/src/modules/maintenance => cli-module-maintenance/src}/index.ts (95%) create mode 100644 packages/cli-module-migrate/.eslintrc.js create mode 100644 packages/cli-module-migrate/catalog-info.yaml create mode 100644 packages/cli-module-migrate/package.json rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/commands/packageExports.ts (93%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/commands/packageLintConfigs.ts (97%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/commands/packageRole.ts (97%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/commands/packageScripts.ts (98%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/commands/reactRouterDeps.ts (97%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/commands/versions/bump.test.ts (100%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/commands/versions/bump.ts (99%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/commands/versions/migrate.test.ts (100%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/commands/versions/migrate.ts (98%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/index.ts (98%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/lib/utils.ts (100%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/lib/versioning/packages.test.ts (100%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/lib/versioning/packages.ts (100%) rename packages/{cli/src/modules/migrate => cli-module-migrate/src}/lib/versioning/yarn.ts (100%) create mode 100644 packages/cli-module-new/.eslintrc.js create mode 100644 packages/cli-module-new/catalog-info.yaml create mode 100644 packages/cli-module-new/package.json rename packages/{cli/src/modules/new => cli-module-new/src}/commands/new.test.ts (96%) rename packages/{cli/src/modules/new => cli-module-new/src}/commands/new.ts (98%) rename packages/{cli/src/modules/new => cli-module-new/src}/index.ts (97%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/codeowners/codeowners.test.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/codeowners/codeowners.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/codeowners/index.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/createNewPackage.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/defaultTemplates.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/execution/PortableTemplater.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/execution/executePortableTemplate.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/execution/index.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/execution/installNewPackage.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/execution/writeTemplateContents.test.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/execution/writeTemplateContents.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/collectPortableTemplateInput.test.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/collectPortableTemplateInput.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/index.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/loadPortableTemplate.test.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/loadPortableTemplate.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/loadPortableTemplateConfig.test.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/loadPortableTemplateConfig.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/resolvePackageParams.test.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/resolvePackageParams.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/selectTemplateInteractively.test.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/preparation/selectTemplateInteractively.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/tasks.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/types.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/version.test.ts (100%) rename packages/{cli/src/modules/new => cli-module-new/src}/lib/version.ts (63%) create mode 100644 packages/cli-module-test-jest/.eslintrc.js create mode 100644 packages/cli-module-test-jest/catalog-info.yaml create mode 100644 packages/cli-module-test-jest/package.json rename packages/{cli/src/modules/test => cli-module-test-jest/src}/commands/package/test.ts (94%) rename packages/{cli/src/modules/test => cli-module-test-jest/src}/commands/repo/test.test.ts (100%) rename packages/{cli/src/modules/test => cli-module-test-jest/src}/commands/repo/test.ts (98%) rename packages/{cli/src/modules/test => cli-module-test-jest/src}/index.ts (96%) create mode 100644 packages/cli-module-translations/.eslintrc.js create mode 100644 packages/cli-module-translations/catalog-info.yaml create mode 100644 packages/cli-module-translations/package.json rename packages/{cli/src/modules/translations => cli-module-translations/src}/commands/export.ts (98%) rename packages/{cli/src/modules/translations => cli-module-translations/src}/commands/import.ts (99%) rename packages/{cli/src/modules/translations => cli-module-translations/src}/index.ts (96%) rename packages/{cli/src/modules/translations => cli-module-translations/src}/lib/discoverPackages.ts (100%) rename packages/{cli/src/modules/translations => cli-module-translations/src}/lib/extractTranslations.test.ts (100%) rename packages/{cli/src/modules/translations => cli-module-translations/src}/lib/extractTranslations.ts (100%) rename packages/{cli/src/modules/translations => cli-module-translations/src}/lib/messageFilePath.test.ts (100%) rename packages/{cli/src/modules/translations => cli-module-translations/src}/lib/messageFilePath.ts (100%) diff --git a/packages/cli-module-auth/.eslintrc.js b/packages/cli-module-auth/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-auth/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-auth/catalog-info.yaml b/packages/cli-module-auth/catalog-info.yaml new file mode 100644 index 0000000000..091bcad199 --- /dev/null +++ b/packages/cli-module-auth/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-auth + title: '@backstage/cli-module-auth' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-auth/package.json b/packages/cli-module-auth/package.json new file mode 100644 index 0000000000..d00b1010f6 --- /dev/null +++ b/packages/cli-module-auth/package.json @@ -0,0 +1,51 @@ +{ + "name": "@backstage/cli-module-auth", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-auth" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-node": "workspace:^", + "@backstage/errors": "workspace:^", + "cleye": "^2.3.0", + "fs-extra": "^11.2.0", + "glob": "^7.1.7", + "inquirer": "^8.2.0", + "proper-lockfile": "^4.1.2", + "yaml": "^2.0.0", + "zod": "^3.25.76" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@types/fs-extra": "^11.0.0", + "@types/proper-lockfile": "^4", + "cross-fetch": "^4.0.0" + } +} diff --git a/packages/cli/src/modules/auth/commands/list.ts b/packages/cli-module-auth/src/commands/list.ts similarity index 94% rename from packages/cli/src/modules/auth/commands/list.ts rename to packages/cli-module-auth/src/commands/list.ts index c27aace3ce..3da2118800 100644 --- a/packages/cli/src/modules/auth/commands/list.ts +++ b/packages/cli-module-auth/src/commands/list.ts @@ -15,7 +15,7 @@ */ import { cli } from 'cleye'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; import { getAllInstances } from '../lib/storage'; export default async ({ args, info }: CliCommandContext) => { diff --git a/packages/cli/src/modules/auth/commands/login.ts b/packages/cli-module-auth/src/commands/login.ts similarity index 99% rename from packages/cli/src/modules/auth/commands/login.ts rename to packages/cli-module-auth/src/commands/login.ts index 8bdd9e0c36..b16060f956 100644 --- a/packages/cli/src/modules/auth/commands/login.ts +++ b/packages/cli-module-auth/src/commands/login.ts @@ -15,7 +15,7 @@ */ import { cli } from 'cleye'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; import { startCallbackServer } from '../lib/localServer'; import { spawn } from 'node:child_process'; import { challengeFromVerifier, generateVerifier } from '../lib/pkce'; diff --git a/packages/cli/src/modules/auth/commands/logout.ts b/packages/cli-module-auth/src/commands/logout.ts similarity index 97% rename from packages/cli/src/modules/auth/commands/logout.ts rename to packages/cli-module-auth/src/commands/logout.ts index ef2e0171b9..f79ed2ef35 100644 --- a/packages/cli/src/modules/auth/commands/logout.ts +++ b/packages/cli-module-auth/src/commands/logout.ts @@ -15,7 +15,7 @@ */ import { cli } from 'cleye'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; import { getSecretStore } from '../lib/secretStore'; import { removeInstance, diff --git a/packages/cli/src/modules/auth/commands/printToken.ts b/packages/cli-module-auth/src/commands/printToken.ts similarity index 96% rename from packages/cli/src/modules/auth/commands/printToken.ts rename to packages/cli-module-auth/src/commands/printToken.ts index e857e39779..39a78c1832 100644 --- a/packages/cli/src/modules/auth/commands/printToken.ts +++ b/packages/cli-module-auth/src/commands/printToken.ts @@ -15,7 +15,7 @@ */ import { cli } from 'cleye'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; import { accessTokenNeedsRefresh, refreshAccessToken } from '../lib/auth'; import { getSelectedInstance } from '../lib/storage'; import { getSecretStore } from '../lib/secretStore'; diff --git a/packages/cli/src/modules/auth/commands/select.ts b/packages/cli-module-auth/src/commands/select.ts similarity index 95% rename from packages/cli/src/modules/auth/commands/select.ts rename to packages/cli-module-auth/src/commands/select.ts index 713b293723..ebce23b1cb 100644 --- a/packages/cli/src/modules/auth/commands/select.ts +++ b/packages/cli-module-auth/src/commands/select.ts @@ -15,7 +15,7 @@ */ import { cli } from 'cleye'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; import { setSelectedInstance } from '../lib/storage'; import { pickInstance } from '../lib/prompt'; diff --git a/packages/cli/src/modules/auth/commands/show.ts b/packages/cli-module-auth/src/commands/show.ts similarity index 97% rename from packages/cli/src/modules/auth/commands/show.ts rename to packages/cli-module-auth/src/commands/show.ts index 8f4ffacfe0..e1b7c62f72 100644 --- a/packages/cli/src/modules/auth/commands/show.ts +++ b/packages/cli-module-auth/src/commands/show.ts @@ -15,7 +15,7 @@ */ import { cli } from 'cleye'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; import { httpJson } from '../lib/http'; import { getSelectedInstance } from '../lib/storage'; import { accessTokenNeedsRefresh, refreshAccessToken } from '../lib/auth'; diff --git a/packages/cli/src/modules/auth/index.ts b/packages/cli-module-auth/src/index.ts similarity index 94% rename from packages/cli/src/modules/auth/index.ts rename to packages/cli-module-auth/src/index.ts index 25876bbece..fef74ec8a5 100644 --- a/packages/cli/src/modules/auth/index.ts +++ b/packages/cli-module-auth/src/index.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { createCliModule } from '../../wiring/factory'; -import packageJson from '../../../package.json'; +import { createCliModule } from '@backstage/cli-node'; +import packageJson from '../package.json'; export default createCliModule({ packageJson, diff --git a/packages/cli/src/modules/auth/lib/auth.test.ts b/packages/cli-module-auth/src/lib/auth.test.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/auth.test.ts rename to packages/cli-module-auth/src/lib/auth.test.ts diff --git a/packages/cli/src/modules/auth/lib/auth.ts b/packages/cli-module-auth/src/lib/auth.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/auth.ts rename to packages/cli-module-auth/src/lib/auth.ts diff --git a/packages/cli/src/modules/auth/lib/http.test.ts b/packages/cli-module-auth/src/lib/http.test.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/http.test.ts rename to packages/cli-module-auth/src/lib/http.test.ts diff --git a/packages/cli/src/modules/auth/lib/http.ts b/packages/cli-module-auth/src/lib/http.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/http.ts rename to packages/cli-module-auth/src/lib/http.ts diff --git a/packages/cli/src/modules/auth/lib/localServer.test.ts b/packages/cli-module-auth/src/lib/localServer.test.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/localServer.test.ts rename to packages/cli-module-auth/src/lib/localServer.test.ts diff --git a/packages/cli/src/modules/auth/lib/localServer.ts b/packages/cli-module-auth/src/lib/localServer.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/localServer.ts rename to packages/cli-module-auth/src/lib/localServer.ts diff --git a/packages/cli/src/modules/auth/lib/pkce.test.ts b/packages/cli-module-auth/src/lib/pkce.test.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/pkce.test.ts rename to packages/cli-module-auth/src/lib/pkce.test.ts diff --git a/packages/cli/src/modules/auth/lib/pkce.ts b/packages/cli-module-auth/src/lib/pkce.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/pkce.ts rename to packages/cli-module-auth/src/lib/pkce.ts diff --git a/packages/cli/src/modules/auth/lib/prompt.test.ts b/packages/cli-module-auth/src/lib/prompt.test.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/prompt.test.ts rename to packages/cli-module-auth/src/lib/prompt.test.ts diff --git a/packages/cli/src/modules/auth/lib/prompt.ts b/packages/cli-module-auth/src/lib/prompt.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/prompt.ts rename to packages/cli-module-auth/src/lib/prompt.ts diff --git a/packages/cli/src/modules/auth/lib/secretStore.test.ts b/packages/cli-module-auth/src/lib/secretStore.test.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/secretStore.test.ts rename to packages/cli-module-auth/src/lib/secretStore.test.ts diff --git a/packages/cli/src/modules/auth/lib/secretStore.ts b/packages/cli-module-auth/src/lib/secretStore.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/secretStore.ts rename to packages/cli-module-auth/src/lib/secretStore.ts diff --git a/packages/cli/src/modules/auth/lib/storage.test.ts b/packages/cli-module-auth/src/lib/storage.test.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/storage.test.ts rename to packages/cli-module-auth/src/lib/storage.test.ts diff --git a/packages/cli/src/modules/auth/lib/storage.ts b/packages/cli-module-auth/src/lib/storage.ts similarity index 100% rename from packages/cli/src/modules/auth/lib/storage.ts rename to packages/cli-module-auth/src/lib/storage.ts diff --git a/packages/cli-module-build/.eslintrc.js b/packages/cli-module-build/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-build/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-build/catalog-info.yaml b/packages/cli-module-build/catalog-info.yaml new file mode 100644 index 0000000000..65715cce2a --- /dev/null +++ b/packages/cli-module-build/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-build + title: '@backstage/cli-module-build' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json new file mode 100644 index 0000000000..0a4849671c --- /dev/null +++ b/packages/cli-module-build/package.json @@ -0,0 +1,92 @@ +{ + "name": "@backstage/cli-module-build", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-build" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/config-loader": "workspace:^", + "@backstage/errors": "workspace:^", + "@manypkg/get-packages": "^1.1.3", + "@module-federation/enhanced": "^0.21.6", + "@pmmmwh/react-refresh-webpack-plugin": "^0.6.2", + "@rollup/plugin-commonjs": "^26.0.0", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.0.0", + "@rollup/plugin-yaml": "^4.0.0", + "@rspack/core": "^1.4.11", + "@rspack/dev-server": "^1.1.4", + "@rspack/plugin-react-refresh": "^1.4.3", + "bfj": "^9.0.2", + "chalk": "^4.0.0", + "chokidar": "^3.5.3", + "cleye": "^2.3.0", + "ctrlc-windows": "^2.1.0", + "esbuild-loader": "^4.4.2", + "eslint-rspack-plugin": "^4.2.1", + "eslint-webpack-plugin": "^5.0.3", + "fork-ts-checker-webpack-plugin": "^9.1.0", + "fs-extra": "^11.2.0", + "glob": "^7.1.7", + "html-webpack-plugin": "^5.6.3", + "lodash": "^4.17.21", + "mini-css-extract-plugin": "^2.10.1", + "node-stdlib-browser": "^1.3.1", + "npm-packlist": "^5.0.0", + "p-queue": "^6.6.2", + "postcss": "^8.1.0", + "postcss-import": "^16.1.0", + "react-dev-utils": "^12.0.0-next.60", + "rollup-plugin-dts": "^6.1.0", + "rollup-plugin-esbuild": "^6.1.1", + "rollup-plugin-postcss": "^4.0.0", + "rollup-pluginutils": "^2.8.2", + "shell-quote": "^1.8.1", + "tar": "^7.5.6", + "ts-checker-rspack-plugin": "^1.1.5", + "webpack": "^5.105.4", + "webpack-dev-server": "^5.2.3", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/module-federation-common": "workspace:^", + "@types/fs-extra": "^11.0.0", + "@types/lodash": "^4.14.151", + "@types/npm-packlist": "^3.0.0", + "@types/shell-quote": "^1.7.5", + "cross-spawn": "^7.0.6", + "rollup": "^4.59.0", + "ts-morph": "^24.0.0" + } +} diff --git a/packages/cli/src/modules/build/commands/buildWorkspace.ts b/packages/cli-module-build/src/commands/buildWorkspace.ts similarity index 96% rename from packages/cli/src/modules/build/commands/buildWorkspace.ts rename to packages/cli-module-build/src/commands/buildWorkspace.ts index fd1ebe16e6..0abd9e5307 100644 --- a/packages/cli/src/modules/build/commands/buildWorkspace.ts +++ b/packages/cli-module-build/src/commands/buildWorkspace.ts @@ -17,7 +17,7 @@ import fs from 'fs-extra'; import { cli } from 'cleye'; import { createDistWorkspace } from '../lib/packager'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { // Normalize legacy --alwaysYarnPack alias (a genuinely different name, not diff --git a/packages/cli/src/modules/build/commands/package/build/command.ts b/packages/cli-module-build/src/commands/package/build/command.ts similarity index 98% rename from packages/cli/src/modules/build/commands/package/build/command.ts rename to packages/cli-module-build/src/commands/package/build/command.ts index a5ba12ea21..07c6e3a8d7 100644 --- a/packages/cli/src/modules/build/commands/package/build/command.ts +++ b/packages/cli-module-build/src/commands/package/build/command.ts @@ -29,7 +29,7 @@ import { buildFrontend } from '../../../lib/buildFrontend'; import { buildBackend } from '../../../lib/buildBackend'; import { isValidUrl } from '../../../lib/urls'; import chalk from 'chalk'; -import type { CliCommandContext } from '../../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { const { diff --git a/packages/cli/src/modules/build/commands/package/build/index.ts b/packages/cli-module-build/src/commands/package/build/index.ts similarity index 100% rename from packages/cli/src/modules/build/commands/package/build/index.ts rename to packages/cli-module-build/src/commands/package/build/index.ts diff --git a/packages/cli/src/modules/build/commands/package/clean.ts b/packages/cli-module-build/src/commands/package/clean.ts similarity index 93% rename from packages/cli/src/modules/build/commands/package/clean.ts rename to packages/cli-module-build/src/commands/package/clean.ts index 9e7ca53d86..fffc418795 100644 --- a/packages/cli/src/modules/build/commands/package/clean.ts +++ b/packages/cli-module-build/src/commands/package/clean.ts @@ -17,7 +17,7 @@ import { cli } from 'cleye'; import fs from 'fs-extra'; import { targetPaths } from '@backstage/cli-common'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); diff --git a/packages/cli/src/modules/build/commands/package/postpack.ts b/packages/cli-module-build/src/commands/package/postpack.ts similarity index 93% rename from packages/cli/src/modules/build/commands/package/postpack.ts rename to packages/cli-module-build/src/commands/package/postpack.ts index a4c64b6071..56856f7401 100644 --- a/packages/cli/src/modules/build/commands/package/postpack.ts +++ b/packages/cli-module-build/src/commands/package/postpack.ts @@ -17,7 +17,7 @@ import { cli } from 'cleye'; import { targetPaths } from '@backstage/cli-common'; import { revertProductionPack } from '../../lib/packager/productionPack'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); diff --git a/packages/cli/src/modules/build/commands/package/prepack.ts b/packages/cli-module-build/src/commands/package/prepack.ts similarity index 95% rename from packages/cli/src/modules/build/commands/package/prepack.ts rename to packages/cli-module-build/src/commands/package/prepack.ts index 8a41f164b8..4488f92c76 100644 --- a/packages/cli/src/modules/build/commands/package/prepack.ts +++ b/packages/cli-module-build/src/commands/package/prepack.ts @@ -20,7 +20,7 @@ import { targetPaths } from '@backstage/cli-common'; import { productionPack } from '../../lib/packager/productionPack'; import { publishPreflightCheck } from '../../lib/publishing'; import { createTypeDistProject } from '../../lib/typeDistProject'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); diff --git a/packages/cli/src/modules/build/commands/package/start/command.ts b/packages/cli-module-build/src/commands/package/start/command.ts similarity index 97% rename from packages/cli/src/modules/build/commands/package/start/command.ts rename to packages/cli-module-build/src/commands/package/start/command.ts index 56adb3889b..8cee25732f 100644 --- a/packages/cli/src/modules/build/commands/package/start/command.ts +++ b/packages/cli-module-build/src/commands/package/start/command.ts @@ -19,7 +19,7 @@ import { startPackage } from './startPackage'; import { resolveLinkedWorkspace } from './resolveLinkedWorkspace'; import { findRoleFromCommand } from '../../../lib/role'; import { targetPaths } from '@backstage/cli-common'; -import type { CliCommandContext } from '../../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { const { diff --git a/packages/cli/src/modules/build/commands/package/start/index.ts b/packages/cli-module-build/src/commands/package/start/index.ts similarity index 100% rename from packages/cli/src/modules/build/commands/package/start/index.ts rename to packages/cli-module-build/src/commands/package/start/index.ts diff --git a/packages/cli/src/modules/build/commands/package/start/resolveLinkedWorkspace.ts b/packages/cli-module-build/src/commands/package/start/resolveLinkedWorkspace.ts similarity index 100% rename from packages/cli/src/modules/build/commands/package/start/resolveLinkedWorkspace.ts rename to packages/cli-module-build/src/commands/package/start/resolveLinkedWorkspace.ts diff --git a/packages/cli/src/modules/build/commands/package/start/startBackend.ts b/packages/cli-module-build/src/commands/package/start/startBackend.ts similarity index 100% rename from packages/cli/src/modules/build/commands/package/start/startBackend.ts rename to packages/cli-module-build/src/commands/package/start/startBackend.ts diff --git a/packages/cli/src/modules/build/commands/package/start/startFrontend.ts b/packages/cli-module-build/src/commands/package/start/startFrontend.ts similarity index 100% rename from packages/cli/src/modules/build/commands/package/start/startFrontend.ts rename to packages/cli-module-build/src/commands/package/start/startFrontend.ts diff --git a/packages/cli/src/modules/build/commands/package/start/startPackage.test.ts b/packages/cli-module-build/src/commands/package/start/startPackage.test.ts similarity index 100% rename from packages/cli/src/modules/build/commands/package/start/startPackage.test.ts rename to packages/cli-module-build/src/commands/package/start/startPackage.test.ts diff --git a/packages/cli/src/modules/build/commands/package/start/startPackage.ts b/packages/cli-module-build/src/commands/package/start/startPackage.ts similarity index 100% rename from packages/cli/src/modules/build/commands/package/start/startPackage.ts rename to packages/cli-module-build/src/commands/package/start/startPackage.ts diff --git a/packages/cli/src/modules/build/commands/repo/build.ts b/packages/cli-module-build/src/commands/repo/build.ts similarity index 98% rename from packages/cli/src/modules/build/commands/repo/build.ts rename to packages/cli-module-build/src/commands/repo/build.ts index 7587ca0cc7..d0bb9cab6c 100644 --- a/packages/cli/src/modules/build/commands/repo/build.ts +++ b/packages/cli-module-build/src/commands/repo/build.ts @@ -29,7 +29,7 @@ import { import { buildFrontend } from '../../lib/buildFrontend'; import { buildBackend } from '../../lib/buildBackend'; import { createScriptOptionsParser } from '../../lib/optionsParser'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { const { diff --git a/packages/cli/src/modules/build/commands/repo/clean.ts b/packages/cli-module-build/src/commands/repo/clean.ts similarity index 96% rename from packages/cli/src/modules/build/commands/repo/clean.ts rename to packages/cli-module-build/src/commands/repo/clean.ts index 99a6d0a77a..12b1daf911 100644 --- a/packages/cli/src/modules/build/commands/repo/clean.ts +++ b/packages/cli-module-build/src/commands/repo/clean.ts @@ -19,7 +19,7 @@ import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; import { PackageGraph } from '@backstage/cli-node'; import { run, targetPaths } from '@backstage/cli-common'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); diff --git a/packages/cli/src/modules/build/commands/repo/start.test.ts b/packages/cli-module-build/src/commands/repo/start.test.ts similarity index 100% rename from packages/cli/src/modules/build/commands/repo/start.test.ts rename to packages/cli-module-build/src/commands/repo/start.test.ts diff --git a/packages/cli/src/modules/build/commands/repo/start.ts b/packages/cli-module-build/src/commands/repo/start.ts similarity index 99% rename from packages/cli/src/modules/build/commands/repo/start.ts rename to packages/cli-module-build/src/commands/repo/start.ts index ab8d8f9279..8cf3dceb1d 100644 --- a/packages/cli/src/modules/build/commands/repo/start.ts +++ b/packages/cli-module-build/src/commands/repo/start.ts @@ -26,7 +26,7 @@ import { cli } from 'cleye'; import { resolveLinkedWorkspace } from '../package/start/resolveLinkedWorkspace'; import { startPackage } from '../package/start/startPackage'; import { parseArgs } from 'node:util'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; const ACCEPTED_PACKAGE_ROLES: Array = [ 'frontend', diff --git a/packages/cli/src/modules/build/index.ts b/packages/cli-module-build/src/index.ts similarity index 98% rename from packages/cli/src/modules/build/index.ts rename to packages/cli-module-build/src/index.ts index ac389c6a68..b2fb597249 100644 --- a/packages/cli/src/modules/build/index.ts +++ b/packages/cli-module-build/src/index.ts @@ -15,7 +15,7 @@ */ import { createCliModule } from '@backstage/cli-node'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export const buildPlugin = createCliModule({ packageJson, diff --git a/packages/cli/src/modules/build/lib/__testUtils__/createFeatureEnvironment.ts b/packages/cli-module-build/src/lib/__testUtils__/createFeatureEnvironment.ts similarity index 100% rename from packages/cli/src/modules/build/lib/__testUtils__/createFeatureEnvironment.ts rename to packages/cli-module-build/src/lib/__testUtils__/createFeatureEnvironment.ts diff --git a/packages/cli/src/modules/build/lib/buildBackend.ts b/packages/cli-module-build/src/lib/buildBackend.ts similarity index 100% rename from packages/cli/src/modules/build/lib/buildBackend.ts rename to packages/cli-module-build/src/lib/buildBackend.ts diff --git a/packages/cli/src/modules/build/lib/buildFrontend.ts b/packages/cli-module-build/src/lib/buildFrontend.ts similarity index 100% rename from packages/cli/src/modules/build/lib/buildFrontend.ts rename to packages/cli-module-build/src/lib/buildFrontend.ts diff --git a/packages/cli/src/modules/build/lib/builder/config.test.ts b/packages/cli-module-build/src/lib/builder/config.test.ts similarity index 100% rename from packages/cli/src/modules/build/lib/builder/config.test.ts rename to packages/cli-module-build/src/lib/builder/config.test.ts diff --git a/packages/cli/src/modules/build/lib/builder/config.ts b/packages/cli-module-build/src/lib/builder/config.ts similarity index 100% rename from packages/cli/src/modules/build/lib/builder/config.ts rename to packages/cli-module-build/src/lib/builder/config.ts diff --git a/packages/cli/src/modules/build/lib/builder/index.ts b/packages/cli-module-build/src/lib/builder/index.ts similarity index 100% rename from packages/cli/src/modules/build/lib/builder/index.ts rename to packages/cli-module-build/src/lib/builder/index.ts diff --git a/packages/cli/src/modules/build/lib/builder/packager.test.ts b/packages/cli-module-build/src/lib/builder/packager.test.ts similarity index 100% rename from packages/cli/src/modules/build/lib/builder/packager.test.ts rename to packages/cli-module-build/src/lib/builder/packager.test.ts diff --git a/packages/cli/src/modules/build/lib/builder/packager.ts b/packages/cli-module-build/src/lib/builder/packager.ts similarity index 100% rename from packages/cli/src/modules/build/lib/builder/packager.ts rename to packages/cli-module-build/src/lib/builder/packager.ts diff --git a/packages/cli/src/modules/build/lib/builder/plugins.test.ts b/packages/cli-module-build/src/lib/builder/plugins.test.ts similarity index 100% rename from packages/cli/src/modules/build/lib/builder/plugins.test.ts rename to packages/cli-module-build/src/lib/builder/plugins.test.ts diff --git a/packages/cli/src/modules/build/lib/builder/plugins.ts b/packages/cli-module-build/src/lib/builder/plugins.ts similarity index 100% rename from packages/cli/src/modules/build/lib/builder/plugins.ts rename to packages/cli-module-build/src/lib/builder/plugins.ts diff --git a/packages/cli/src/modules/build/lib/builder/types.ts b/packages/cli-module-build/src/lib/builder/types.ts similarity index 100% rename from packages/cli/src/modules/build/lib/builder/types.ts rename to packages/cli-module-build/src/lib/builder/types.ts diff --git a/packages/cli/src/modules/build/lib/bundler/ConfigInjectingHtmlWebpackPlugin.ts b/packages/cli-module-build/src/lib/bundler/ConfigInjectingHtmlWebpackPlugin.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/ConfigInjectingHtmlWebpackPlugin.ts rename to packages/cli-module-build/src/lib/bundler/ConfigInjectingHtmlWebpackPlugin.ts diff --git a/packages/cli/src/modules/build/lib/bundler/bundle.ts b/packages/cli-module-build/src/lib/bundler/bundle.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/bundle.ts rename to packages/cli-module-build/src/lib/bundler/bundle.ts diff --git a/packages/cli/src/modules/build/lib/bundler/config.ts b/packages/cli-module-build/src/lib/bundler/config.ts similarity index 99% rename from packages/cli/src/modules/build/lib/bundler/config.ts rename to packages/cli-module-build/src/lib/bundler/config.ts index c3676ecf70..9fbda57f27 100644 --- a/packages/cli/src/modules/build/lib/bundler/config.ts +++ b/packages/cli-module-build/src/lib/bundler/config.ts @@ -32,7 +32,7 @@ import pickBy from 'lodash/pickBy'; import { runOutput, targetPaths } from '@backstage/cli-common'; import { transforms } from './transforms'; -import { version } from '../../../../wiring/version'; +const { version } = require('../../../../package.json') as { version: string }; import yn from 'yn'; import { hasReactDomClient } from './hasReactDomClient'; import { createWorkspaceLinkingPlugins } from './linkWorkspaces'; diff --git a/packages/cli/src/modules/build/lib/bundler/hasReactDomClient.ts b/packages/cli-module-build/src/lib/bundler/hasReactDomClient.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/hasReactDomClient.ts rename to packages/cli-module-build/src/lib/bundler/hasReactDomClient.ts diff --git a/packages/cli/src/modules/build/lib/bundler/index.ts b/packages/cli-module-build/src/lib/bundler/index.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/index.ts rename to packages/cli-module-build/src/lib/bundler/index.ts diff --git a/packages/cli/src/modules/build/lib/bundler/linkWorkspaces.ts b/packages/cli-module-build/src/lib/bundler/linkWorkspaces.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/linkWorkspaces.ts rename to packages/cli-module-build/src/lib/bundler/linkWorkspaces.ts diff --git a/packages/cli/src/modules/build/lib/bundler/moduleFederation.test.ts b/packages/cli-module-build/src/lib/bundler/moduleFederation.test.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/moduleFederation.test.ts rename to packages/cli-module-build/src/lib/bundler/moduleFederation.test.ts diff --git a/packages/cli/src/modules/build/lib/bundler/moduleFederation.ts b/packages/cli-module-build/src/lib/bundler/moduleFederation.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/moduleFederation.ts rename to packages/cli-module-build/src/lib/bundler/moduleFederation.ts diff --git a/packages/cli/src/modules/build/lib/bundler/optimization.ts b/packages/cli-module-build/src/lib/bundler/optimization.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/optimization.ts rename to packages/cli-module-build/src/lib/bundler/optimization.ts diff --git a/packages/cli/src/modules/build/lib/bundler/packageDetection.ts b/packages/cli-module-build/src/lib/bundler/packageDetection.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/packageDetection.ts rename to packages/cli-module-build/src/lib/bundler/packageDetection.ts diff --git a/packages/cli/src/modules/build/lib/bundler/paths.ts b/packages/cli-module-build/src/lib/bundler/paths.ts similarity index 94% rename from packages/cli/src/modules/build/lib/bundler/paths.ts rename to packages/cli-module-build/src/lib/bundler/paths.ts index 5a7d3b14dc..2f2cb0d5d2 100644 --- a/packages/cli/src/modules/build/lib/bundler/paths.ts +++ b/packages/cli-module-build/src/lib/bundler/paths.ts @@ -16,7 +16,7 @@ import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; -import { targetPaths, findOwnPaths } from '@backstage/cli-common'; +import { targetPaths } from '@backstage/cli-common'; export type BundlingPathsOptions = { // bundle entrypoint, e.g. 'src/index' @@ -50,8 +50,8 @@ export function resolveBundlingPaths(options: BundlingPathsOptions) { targetHtml = resolvePath(targetDir, `${entry}.html`); if (!fs.pathExistsSync(targetHtml)) { /* eslint-disable-next-line no-restricted-syntax */ - targetHtml = findOwnPaths(__dirname).resolve( - 'templates/serve_index.html', + targetHtml = require.resolve( + '@backstage/cli/templates/serve_index.html', ); } } diff --git a/packages/cli/src/modules/build/lib/bundler/server.ts b/packages/cli-module-build/src/lib/bundler/server.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/server.ts rename to packages/cli-module-build/src/lib/bundler/server.ts diff --git a/packages/cli/src/modules/build/lib/bundler/transforms.ts b/packages/cli-module-build/src/lib/bundler/transforms.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/transforms.ts rename to packages/cli-module-build/src/lib/bundler/transforms.ts diff --git a/packages/cli/src/modules/build/lib/bundler/types.ts b/packages/cli-module-build/src/lib/bundler/types.ts similarity index 100% rename from packages/cli/src/modules/build/lib/bundler/types.ts rename to packages/cli-module-build/src/lib/bundler/types.ts diff --git a/packages/cli/src/modules/build/lib/config.ts b/packages/cli-module-build/src/lib/config.ts similarity index 100% rename from packages/cli/src/modules/build/lib/config.ts rename to packages/cli-module-build/src/lib/config.ts diff --git a/packages/cli/src/modules/build/lib/entryPoints.ts b/packages/cli-module-build/src/lib/entryPoints.ts similarity index 100% rename from packages/cli/src/modules/build/lib/entryPoints.ts rename to packages/cli-module-build/src/lib/entryPoints.ts diff --git a/packages/cli/src/modules/build/lib/ipc/IpcServer.ts b/packages/cli-module-build/src/lib/ipc/IpcServer.ts similarity index 100% rename from packages/cli/src/modules/build/lib/ipc/IpcServer.ts rename to packages/cli-module-build/src/lib/ipc/IpcServer.ts diff --git a/packages/cli/src/modules/build/lib/ipc/ServerDataStore.ts b/packages/cli-module-build/src/lib/ipc/ServerDataStore.ts similarity index 100% rename from packages/cli/src/modules/build/lib/ipc/ServerDataStore.ts rename to packages/cli-module-build/src/lib/ipc/ServerDataStore.ts diff --git a/packages/cli/src/modules/build/lib/ipc/index.ts b/packages/cli-module-build/src/lib/ipc/index.ts similarity index 100% rename from packages/cli/src/modules/build/lib/ipc/index.ts rename to packages/cli-module-build/src/lib/ipc/index.ts diff --git a/packages/cli/src/modules/build/lib/optionsParser.ts b/packages/cli-module-build/src/lib/optionsParser.ts similarity index 100% rename from packages/cli/src/modules/build/lib/optionsParser.ts rename to packages/cli-module-build/src/lib/optionsParser.ts diff --git a/packages/cli/src/modules/build/lib/packager/createDistWorkspace.ts b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts similarity index 98% rename from packages/cli/src/modules/build/lib/packager/createDistWorkspace.ts rename to packages/cli-module-build/src/lib/packager/createDistWorkspace.ts index 9f63525186..52ceaaf355 100644 --- a/packages/cli/src/modules/build/lib/packager/createDistWorkspace.ts +++ b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts @@ -27,10 +27,13 @@ import partition from 'lodash/partition'; import { run, targetPaths } from '@backstage/cli-common'; -import { - dependencies as cliDependencies, - devDependencies as cliDevDependencies, -} from '../../../../../package.json'; +const { + dependencies: cliDependencies, + devDependencies: cliDevDependencies, +} = require('../../../../package.json') as { + dependencies: Record; + devDependencies: Record; +}; import { BuildOptions, buildPackages, diff --git a/packages/cli/src/modules/build/lib/packager/index.ts b/packages/cli-module-build/src/lib/packager/index.ts similarity index 100% rename from packages/cli/src/modules/build/lib/packager/index.ts rename to packages/cli-module-build/src/lib/packager/index.ts diff --git a/packages/cli/src/modules/build/lib/packager/productionPack.ts b/packages/cli-module-build/src/lib/packager/productionPack.ts similarity index 100% rename from packages/cli/src/modules/build/lib/packager/productionPack.ts rename to packages/cli-module-build/src/lib/packager/productionPack.ts diff --git a/packages/cli/src/modules/build/lib/publishing.ts b/packages/cli-module-build/src/lib/publishing.ts similarity index 100% rename from packages/cli/src/modules/build/lib/publishing.ts rename to packages/cli-module-build/src/lib/publishing.ts diff --git a/packages/cli/src/modules/build/lib/role.test.ts b/packages/cli-module-build/src/lib/role.test.ts similarity index 100% rename from packages/cli/src/modules/build/lib/role.test.ts rename to packages/cli-module-build/src/lib/role.test.ts diff --git a/packages/cli/src/modules/build/lib/role.ts b/packages/cli-module-build/src/lib/role.ts similarity index 100% rename from packages/cli/src/modules/build/lib/role.ts rename to packages/cli-module-build/src/lib/role.ts diff --git a/packages/cli/src/modules/build/lib/runner/index.ts b/packages/cli-module-build/src/lib/runner/index.ts similarity index 100% rename from packages/cli/src/modules/build/lib/runner/index.ts rename to packages/cli-module-build/src/lib/runner/index.ts diff --git a/packages/cli/src/modules/build/lib/runner/runBackend.test.ts b/packages/cli-module-build/src/lib/runner/runBackend.test.ts similarity index 100% rename from packages/cli/src/modules/build/lib/runner/runBackend.test.ts rename to packages/cli-module-build/src/lib/runner/runBackend.test.ts diff --git a/packages/cli/src/modules/build/lib/runner/runBackend.ts b/packages/cli-module-build/src/lib/runner/runBackend.ts similarity index 100% rename from packages/cli/src/modules/build/lib/runner/runBackend.ts rename to packages/cli-module-build/src/lib/runner/runBackend.ts diff --git a/packages/cli/src/modules/build/lib/typeDistProject.test.ts b/packages/cli-module-build/src/lib/typeDistProject.test.ts similarity index 100% rename from packages/cli/src/modules/build/lib/typeDistProject.test.ts rename to packages/cli-module-build/src/lib/typeDistProject.test.ts diff --git a/packages/cli/src/modules/build/lib/typeDistProject.ts b/packages/cli-module-build/src/lib/typeDistProject.ts similarity index 100% rename from packages/cli/src/modules/build/lib/typeDistProject.ts rename to packages/cli-module-build/src/lib/typeDistProject.ts diff --git a/packages/cli/src/modules/build/lib/urls.test.ts b/packages/cli-module-build/src/lib/urls.test.ts similarity index 100% rename from packages/cli/src/modules/build/lib/urls.test.ts rename to packages/cli-module-build/src/lib/urls.test.ts diff --git a/packages/cli/src/modules/build/lib/urls.ts b/packages/cli-module-build/src/lib/urls.ts similarity index 100% rename from packages/cli/src/modules/build/lib/urls.ts rename to packages/cli-module-build/src/lib/urls.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/.gitignore b/packages/cli-module-build/src/tests/transforms/__fixtures__/.gitignore similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/.gitignore rename to packages/cli-module-build/src/tests/transforms/__fixtures__/.gitignore diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-default.js b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-default.js similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-default.js rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-default.js diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-named.js b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-named.js similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-named.js rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/a-named.js diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-default.mjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-default.mjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-default.mjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-default.mjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-named.mjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-named.mjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-named.mjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/b-named.mjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-default.cjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-default.cjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-default.cjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-default.cjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-named.cjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-named.cjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-named.cjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/c-named.cjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.d.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.d.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.d.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.d.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.js b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.js similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.js rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/main.js diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/package.json b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/package.json similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-commonjs/package.json rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-commonjs/package.json diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/a-default.js b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/a-default.js similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/a-default.js rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/a-default.js diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/a-named.js b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/a-named.js similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/a-named.js rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/a-named.js diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/b-default.mjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/b-default.mjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/b-default.mjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/b-default.mjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/b-named.mjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/b-named.mjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/b-named.mjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/b-named.mjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/c-default.cjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/c-default.cjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/c-default.cjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/c-default.cjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/c-named.cjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/c-named.cjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/c-named.cjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/c-named.cjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/main.d.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/main.d.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/main.d.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/main.d.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/main.js b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/main.js similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/main.js rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/main.js diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/package.json b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/package.json similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-default/package.json rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-default/package.json diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/a-default.js b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/a-default.js similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/a-default.js rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/a-default.js diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/a-named.js b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/a-named.js similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/a-named.js rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/a-named.js diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/b-default.mjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/b-default.mjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/b-default.mjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/b-default.mjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/b-named.mjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/b-named.mjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/b-named.mjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/b-named.mjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/c-default.cjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/c-default.cjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/c-default.cjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/c-default.cjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/c-named.cjs b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/c-named.cjs similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/c-named.cjs rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/c-named.cjs diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/main.d.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/main.d.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/main.d.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/main.d.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/main.js b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/main.js similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/main.js rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/main.js diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/package.json b/packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/package.json similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/node_modules/dep-module/package.json rename to packages/cli-module-build/src/tests/transforms/__fixtures__/node_modules/dep-module/package.json diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/a-default.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/a-default.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/a-default.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/a-default.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/a-named.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/a-named.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/a-named.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/a-named.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/b-default.mts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/b-default.mts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/b-default.mts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/b-default.mts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/b-named.mts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/b-named.mts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/b-named.mts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/b-named.mts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/c-default.cts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/c-default.cts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/c-default.cts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/c-default.cts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/c-named.cts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/c-named.cts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/c-named.cts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/c-named.cts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/main.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/main.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/main.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/main.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/package.json b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/package.json similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/package.json rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/package.json diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/print.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/print.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-commonjs/print.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-commonjs/print.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/a-default.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/a-default.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/a-default.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/a-default.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/a-named.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/a-named.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/a-named.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/a-named.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/b-default.mts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/b-default.mts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/b-default.mts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/b-default.mts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/b-named.mts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/b-named.mts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/b-named.mts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/b-named.mts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/c-default.cts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/c-default.cts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/c-default.cts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/c-default.cts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/c-named.cts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/c-named.cts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/c-named.cts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/c-named.cts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/main.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/main.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/main.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/main.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/package.json b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/package.json similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/package.json rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/package.json diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/print.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/print.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-default/print.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-default/print.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/a-default-explicit.mts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/a-default-explicit.mts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/a-default-explicit.mts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/a-default-explicit.mts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/a-default.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/a-default.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/a-default.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/a-default.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/a-named-explicit.mts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/a-named-explicit.mts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/a-named-explicit.mts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/a-named-explicit.mts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/a-named.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/a-named.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/a-named.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/a-named.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/b-default.mts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/b-default.mts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/b-default.mts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/b-default.mts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/b-named.mts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/b-named.mts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/b-named.mts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/b-named.mts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/c-default.cts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/c-default.cts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/c-default.cts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/c-default.cts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/c-named.cts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/c-named.cts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/c-named.cts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/c-named.cts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/main-explicit.mts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/main-explicit.mts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/main-explicit.mts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/main-explicit.mts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/main.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/main.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/main.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/main.ts diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/package.json b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/package.json similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/package.json rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/package.json diff --git a/packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/print.ts b/packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/print.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/__fixtures__/pkg-module/print.ts rename to packages/cli-module-build/src/tests/transforms/__fixtures__/pkg-module/print.ts diff --git a/packages/cli/src/modules/build/tests/transforms/transforms.test.ts b/packages/cli-module-build/src/tests/transforms/transforms.test.ts similarity index 100% rename from packages/cli/src/modules/build/tests/transforms/transforms.test.ts rename to packages/cli-module-build/src/tests/transforms/transforms.test.ts diff --git a/packages/cli-module-config/.eslintrc.js b/packages/cli-module-config/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-config/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-config/catalog-info.yaml b/packages/cli-module-config/catalog-info.yaml new file mode 100644 index 0000000000..b7c5d61aba --- /dev/null +++ b/packages/cli-module-config/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-config + title: '@backstage/cli-module-config' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-config/package.json b/packages/cli-module-config/package.json new file mode 100644 index 0000000000..841f40de35 --- /dev/null +++ b/packages/cli-module-config/package.json @@ -0,0 +1,50 @@ +{ + "name": "@backstage/cli-module-config", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-config" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/config-loader": "workspace:^", + "@backstage/types": "workspace:^", + "@manypkg/get-packages": "^1.1.3", + "@types/json-schema": "^7.0.6", + "chalk": "^4.0.0", + "cleye": "^2.3.0", + "json-schema": "^0.4.0", + "react-dev-utils": "^12.0.0-next.60", + "yaml": "^2.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } +} diff --git a/packages/cli/src/modules/config/commands/docs.ts b/packages/cli-module-config/src/commands/docs.ts similarity index 97% rename from packages/cli/src/modules/config/commands/docs.ts rename to packages/cli-module-config/src/commands/docs.ts index ff9955ddba..54cc1832f5 100644 --- a/packages/cli/src/modules/config/commands/docs.ts +++ b/packages/cli-module-config/src/commands/docs.ts @@ -21,7 +21,7 @@ import { JSONSchema7 as JSONSchema } from 'json-schema'; import openBrowser from 'react-dev-utils/openBrowser'; import chalk from 'chalk'; import { loadCliConfig } from '../lib/config'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; const DOCS_URL = 'https://config.backstage.io'; diff --git a/packages/cli/src/modules/config/commands/print.ts b/packages/cli-module-config/src/commands/print.ts similarity index 98% rename from packages/cli/src/modules/config/commands/print.ts rename to packages/cli-module-config/src/commands/print.ts index fdde6fcb5d..08f785b1d0 100644 --- a/packages/cli/src/modules/config/commands/print.ts +++ b/packages/cli-module-config/src/commands/print.ts @@ -19,7 +19,7 @@ import { stringify as stringifyYaml } from 'yaml'; import { AppConfig, ConfigReader } from '@backstage/config'; import { loadCliConfig } from '../lib/config'; import { ConfigSchema, ConfigVisibility } from '@backstage/config-loader'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { const { diff --git a/packages/cli/src/modules/config/commands/schema.ts b/packages/cli-module-config/src/commands/schema.ts similarity index 97% rename from packages/cli/src/modules/config/commands/schema.ts rename to packages/cli-module-config/src/commands/schema.ts index 989fcdbc26..4eaa8189ba 100644 --- a/packages/cli/src/modules/config/commands/schema.ts +++ b/packages/cli-module-config/src/commands/schema.ts @@ -20,7 +20,7 @@ import { stringify as stringifyYaml } from 'yaml'; import { loadCliConfig } from '../lib/config'; import { JsonObject } from '@backstage/types'; import { mergeConfigSchemas } from '@backstage/config-loader'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { const { diff --git a/packages/cli/src/modules/config/commands/validate.ts b/packages/cli-module-config/src/commands/validate.ts similarity index 96% rename from packages/cli/src/modules/config/commands/validate.ts rename to packages/cli-module-config/src/commands/validate.ts index 78505f76bf..326c6b5e42 100644 --- a/packages/cli/src/modules/config/commands/validate.ts +++ b/packages/cli-module-config/src/commands/validate.ts @@ -16,7 +16,7 @@ import { cli } from 'cleye'; import { loadCliConfig } from '../lib/config'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { const { diff --git a/packages/cli/src/modules/config/index.ts b/packages/cli-module-config/src/index.ts similarity index 97% rename from packages/cli/src/modules/config/index.ts rename to packages/cli-module-config/src/index.ts index 89a7d90111..af2a7143b7 100644 --- a/packages/cli/src/modules/config/index.ts +++ b/packages/cli-module-config/src/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { createCliModule } from '@backstage/cli-node'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export const configOption = [ '--config ', diff --git a/packages/cli/src/modules/config/lib/config.ts b/packages/cli-module-config/src/lib/config.ts similarity index 100% rename from packages/cli/src/modules/config/lib/config.ts rename to packages/cli-module-config/src/lib/config.ts diff --git a/packages/cli-module-create-github-app/.eslintrc.js b/packages/cli-module-create-github-app/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-create-github-app/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-create-github-app/catalog-info.yaml b/packages/cli-module-create-github-app/catalog-info.yaml new file mode 100644 index 0000000000..66e59c5a27 --- /dev/null +++ b/packages/cli-module-create-github-app/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-create-github-app + title: '@backstage/cli-module-create-github-app' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-create-github-app/package.json b/packages/cli-module-create-github-app/package.json new file mode 100644 index 0000000000..878ac0b3f8 --- /dev/null +++ b/packages/cli-module-create-github-app/package.json @@ -0,0 +1,50 @@ +{ + "name": "@backstage/cli-module-create-github-app", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-create-github-app" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", + "@octokit/request": "^8.0.0", + "@types/express": "^4.17.6", + "chalk": "^4.0.0", + "cleye": "^2.3.0", + "express": "^4.22.0", + "fs-extra": "^11.2.0", + "inquirer": "^8.2.0", + "react-dev-utils": "^12.0.0-next.60", + "yaml": "^2.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@types/fs-extra": "^11.0.0" + } +} diff --git a/packages/cli/src/modules/create-github-app/commands/create-github-app/GithubCreateAppServer.ts b/packages/cli-module-create-github-app/src/commands/create-github-app/GithubCreateAppServer.ts similarity index 100% rename from packages/cli/src/modules/create-github-app/commands/create-github-app/GithubCreateAppServer.ts rename to packages/cli-module-create-github-app/src/commands/create-github-app/GithubCreateAppServer.ts diff --git a/packages/cli/src/modules/create-github-app/commands/create-github-app/index.ts b/packages/cli-module-create-github-app/src/commands/create-github-app/index.ts similarity index 98% rename from packages/cli/src/modules/create-github-app/commands/create-github-app/index.ts rename to packages/cli-module-create-github-app/src/commands/create-github-app/index.ts index 25f3847b42..bb6896c9c1 100644 --- a/packages/cli/src/modules/create-github-app/commands/create-github-app/index.ts +++ b/packages/cli-module-create-github-app/src/commands/create-github-app/index.ts @@ -23,7 +23,7 @@ import { cli } from 'cleye'; import { GithubCreateAppServer } from './GithubCreateAppServer'; import openBrowser from 'react-dev-utils/openBrowser'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; // This is an experimental command that at this point does not support GitHub Enterprise // due to lacking support for creating apps from manifests. diff --git a/packages/cli/src/modules/create-github-app/index.ts b/packages/cli-module-create-github-app/src/index.ts similarity index 95% rename from packages/cli/src/modules/create-github-app/index.ts rename to packages/cli-module-create-github-app/src/index.ts index 04786cbbdb..c3bd7cf95f 100644 --- a/packages/cli/src/modules/create-github-app/index.ts +++ b/packages/cli-module-create-github-app/src/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { createCliModule } from '@backstage/cli-node'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export default createCliModule({ packageJson, diff --git a/packages/cli-module-info/.eslintrc.js b/packages/cli-module-info/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-info/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-info/catalog-info.yaml b/packages/cli-module-info/catalog-info.yaml new file mode 100644 index 0000000000..2f6eb65952 --- /dev/null +++ b/packages/cli-module-info/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-info + title: '@backstage/cli-module-info' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-info/package.json b/packages/cli-module-info/package.json new file mode 100644 index 0000000000..5e1dd894e9 --- /dev/null +++ b/packages/cli-module-info/package.json @@ -0,0 +1,44 @@ +{ + "name": "@backstage/cli-module-info", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-info" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", + "cleye": "^2.3.0", + "fs-extra": "^11.2.0", + "minimatch": "^10.2.1" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@types/fs-extra": "^11.0.0" + } +} diff --git a/packages/cli/src/modules/info/commands/info.ts b/packages/cli-module-info/src/commands/info.ts similarity index 97% rename from packages/cli/src/modules/info/commands/info.ts rename to packages/cli-module-info/src/commands/info.ts index 306bb54f4a..dd9f892d27 100644 --- a/packages/cli/src/modules/info/commands/info.ts +++ b/packages/cli-module-info/src/commands/info.ts @@ -15,7 +15,9 @@ */ import { cli } from 'cleye'; -import { version as cliVersion } from '../../../../package.json'; +const { version: cliVersion } = require('../../../package.json') as { + version: string; +}; import os from 'node:os'; import { runOutput, targetPaths, findOwnPaths } from '@backstage/cli-common'; import { @@ -25,7 +27,7 @@ import { } from '@backstage/cli-node'; import { minimatch } from 'minimatch'; import fs from 'fs-extra'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; /** * Attempts to read package.json from node_modules for a given package name. diff --git a/packages/cli/src/modules/info/index.ts b/packages/cli-module-info/src/index.ts similarity index 95% rename from packages/cli/src/modules/info/index.ts rename to packages/cli-module-info/src/index.ts index c4a839ff12..c7ace24bbd 100644 --- a/packages/cli/src/modules/info/index.ts +++ b/packages/cli-module-info/src/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { createCliModule } from '@backstage/cli-node'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export default createCliModule({ packageJson, diff --git a/packages/cli-module-lint/.eslintrc.js b/packages/cli-module-lint/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-lint/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-lint/catalog-info.yaml b/packages/cli-module-lint/catalog-info.yaml new file mode 100644 index 0000000000..d40b7e23e3 --- /dev/null +++ b/packages/cli-module-lint/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-lint + title: '@backstage/cli-module-lint' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-lint/package.json b/packages/cli-module-lint/package.json new file mode 100644 index 0000000000..40839a0046 --- /dev/null +++ b/packages/cli-module-lint/package.json @@ -0,0 +1,48 @@ +{ + "name": "@backstage/cli-module-lint", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-lint" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", + "chalk": "^4.0.0", + "cleye": "^2.3.0", + "eslint": "^8.6.0", + "fs-extra": "^11.2.0", + "globby": "^11.0.0", + "shell-quote": "^1.8.1" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@types/fs-extra": "^11.0.0", + "@types/shell-quote": "^1.7.5" + } +} diff --git a/packages/cli/src/modules/lint/commands/package/lint.ts b/packages/cli-module-lint/src/commands/package/lint.ts similarity index 97% rename from packages/cli/src/modules/lint/commands/package/lint.ts rename to packages/cli-module-lint/src/commands/package/lint.ts index de6716ec0a..7fabf0c0ff 100644 --- a/packages/cli/src/modules/lint/commands/package/lint.ts +++ b/packages/cli-module-lint/src/commands/package/lint.ts @@ -18,7 +18,7 @@ import fs from 'fs-extra'; import { cli } from 'cleye'; import { targetPaths } from '@backstage/cli-common'; import { ESLint } from 'eslint'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { const { diff --git a/packages/cli/src/modules/lint/commands/repo/lint.ts b/packages/cli-module-lint/src/commands/repo/lint.ts similarity index 99% rename from packages/cli/src/modules/lint/commands/repo/lint.ts rename to packages/cli-module-lint/src/commands/repo/lint.ts index 1598c44c54..01dfad6339 100644 --- a/packages/cli/src/modules/lint/commands/repo/lint.ts +++ b/packages/cli-module-lint/src/commands/repo/lint.ts @@ -29,7 +29,7 @@ import { import { targetPaths } from '@backstage/cli-common'; import { createScriptOptionsParser } from '../../lib/optionsParser'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; function depCount(pkg: BackstagePackageJson) { const deps = pkg.dependencies ? Object.keys(pkg.dependencies).length : 0; diff --git a/packages/cli/src/modules/lint/index.ts b/packages/cli-module-lint/src/index.ts similarity index 95% rename from packages/cli/src/modules/lint/index.ts rename to packages/cli-module-lint/src/index.ts index 71961a147f..d202841e79 100644 --- a/packages/cli/src/modules/lint/index.ts +++ b/packages/cli-module-lint/src/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { createCliModule } from '@backstage/cli-node'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export default createCliModule({ packageJson, diff --git a/packages/cli/src/modules/lint/lib/optionsParser.ts b/packages/cli-module-lint/src/lib/optionsParser.ts similarity index 100% rename from packages/cli/src/modules/lint/lib/optionsParser.ts rename to packages/cli-module-lint/src/lib/optionsParser.ts diff --git a/packages/cli-module-maintenance/.eslintrc.js b/packages/cli-module-maintenance/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-maintenance/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-maintenance/catalog-info.yaml b/packages/cli-module-maintenance/catalog-info.yaml new file mode 100644 index 0000000000..df05034045 --- /dev/null +++ b/packages/cli-module-maintenance/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-maintenance + title: '@backstage/cli-module-maintenance' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-maintenance/package.json b/packages/cli-module-maintenance/package.json new file mode 100644 index 0000000000..5d321f88f0 --- /dev/null +++ b/packages/cli-module-maintenance/package.json @@ -0,0 +1,45 @@ +{ + "name": "@backstage/cli-module-maintenance", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-maintenance" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", + "chalk": "^4.0.0", + "cleye": "^2.3.0", + "eslint": "^8.6.0", + "fs-extra": "^11.2.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@types/fs-extra": "^11.0.0" + } +} diff --git a/packages/cli/src/modules/maintenance/commands/repo/fix.ts b/packages/cli-module-maintenance/src/commands/repo/fix.ts similarity index 99% rename from packages/cli/src/modules/maintenance/commands/repo/fix.ts rename to packages/cli-module-maintenance/src/commands/repo/fix.ts index 147779443d..4d6445fe86 100644 --- a/packages/cli/src/modules/maintenance/commands/repo/fix.ts +++ b/packages/cli-module-maintenance/src/commands/repo/fix.ts @@ -505,7 +505,7 @@ type PackageFixer = (pkg: FixablePackage, packages: FixablePackage[]) => void; export default async ({ args, info, -}: import('../../../../wiring/types').CliCommandContext) => { +}: import('@backstage/cli-node').CliCommandContext) => { const { flags: { publish, check }, } = cli( diff --git a/packages/cli/src/modules/maintenance/commands/repo/list-deprecations.ts b/packages/cli-module-maintenance/src/commands/repo/list-deprecations.ts similarity index 97% rename from packages/cli/src/modules/maintenance/commands/repo/list-deprecations.ts rename to packages/cli-module-maintenance/src/commands/repo/list-deprecations.ts index b594920027..e711cb32be 100644 --- a/packages/cli/src/modules/maintenance/commands/repo/list-deprecations.ts +++ b/packages/cli-module-maintenance/src/commands/repo/list-deprecations.ts @@ -20,7 +20,7 @@ import { cli } from 'cleye'; import { relative as relativePath } from 'node:path'; import { PackageGraph } from '@backstage/cli-node'; import { targetPaths } from '@backstage/cli-common'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { const { diff --git a/packages/cli/src/modules/maintenance/index.ts b/packages/cli-module-maintenance/src/index.ts similarity index 95% rename from packages/cli/src/modules/maintenance/index.ts rename to packages/cli-module-maintenance/src/index.ts index 315d222448..77304eef47 100644 --- a/packages/cli/src/modules/maintenance/index.ts +++ b/packages/cli-module-maintenance/src/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { createCliModule } from '@backstage/cli-node'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export default createCliModule({ packageJson, diff --git a/packages/cli-module-migrate/.eslintrc.js b/packages/cli-module-migrate/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-migrate/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-migrate/catalog-info.yaml b/packages/cli-module-migrate/catalog-info.yaml new file mode 100644 index 0000000000..5c62edf9ba --- /dev/null +++ b/packages/cli-module-migrate/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-migrate + title: '@backstage/cli-module-migrate' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-migrate/package.json b/packages/cli-module-migrate/package.json new file mode 100644 index 0000000000..660b85dff2 --- /dev/null +++ b/packages/cli-module-migrate/package.json @@ -0,0 +1,48 @@ +{ + "name": "@backstage/cli-module-migrate", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-migrate" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", + "@manypkg/get-packages": "^1.1.3", + "cleye": "^2.3.0", + "fs-extra": "^11.2.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@types/fs-extra": "^11.0.0", + "msw": "^1.0.0" + } +} diff --git a/packages/cli/src/modules/migrate/commands/packageExports.ts b/packages/cli-module-migrate/src/commands/packageExports.ts similarity index 93% rename from packages/cli/src/modules/migrate/commands/packageExports.ts rename to packages/cli-module-migrate/src/commands/packageExports.ts index 68cb14a01e..8a4ad45f42 100644 --- a/packages/cli/src/modules/migrate/commands/packageExports.ts +++ b/packages/cli-module-migrate/src/commands/packageExports.ts @@ -15,7 +15,7 @@ */ import { cli } from 'cleye'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); diff --git a/packages/cli/src/modules/migrate/commands/packageLintConfigs.ts b/packages/cli-module-migrate/src/commands/packageLintConfigs.ts similarity index 97% rename from packages/cli/src/modules/migrate/commands/packageLintConfigs.ts rename to packages/cli-module-migrate/src/commands/packageLintConfigs.ts index be316b0bf5..660ed35bb6 100644 --- a/packages/cli/src/modules/migrate/commands/packageLintConfigs.ts +++ b/packages/cli-module-migrate/src/commands/packageLintConfigs.ts @@ -19,7 +19,7 @@ import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; import { PackageGraph } from '@backstage/cli-node'; import { runOutput } from '@backstage/cli-common'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; const PREFIX = `module.exports = require('@backstage/cli/config/eslint-factory')`; diff --git a/packages/cli/src/modules/migrate/commands/packageRole.ts b/packages/cli-module-migrate/src/commands/packageRole.ts similarity index 97% rename from packages/cli/src/modules/migrate/commands/packageRole.ts rename to packages/cli-module-migrate/src/commands/packageRole.ts index d9f775e2d0..8758d48dd5 100644 --- a/packages/cli/src/modules/migrate/commands/packageRole.ts +++ b/packages/cli-module-migrate/src/commands/packageRole.ts @@ -20,7 +20,7 @@ import { resolve as resolvePath } from 'node:path'; import { getPackages } from '@manypkg/get-packages'; import { PackageRoles } from '@backstage/cli-node'; import { targetPaths } from '@backstage/cli-common'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { cli({ help: info, booleanFlagNegation: true }, undefined, args); diff --git a/packages/cli/src/modules/migrate/commands/packageScripts.ts b/packages/cli-module-migrate/src/commands/packageScripts.ts similarity index 98% rename from packages/cli/src/modules/migrate/commands/packageScripts.ts rename to packages/cli-module-migrate/src/commands/packageScripts.ts index b9bc9d6656..94a05f67f9 100644 --- a/packages/cli/src/modules/migrate/commands/packageScripts.ts +++ b/packages/cli-module-migrate/src/commands/packageScripts.ts @@ -18,7 +18,7 @@ import { cli } from 'cleye'; import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; import { PackageGraph, PackageRoles, PackageRole } from '@backstage/cli-node'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; const configArgPattern = /--config[=\s][^\s$]+/; diff --git a/packages/cli/src/modules/migrate/commands/reactRouterDeps.ts b/packages/cli-module-migrate/src/commands/reactRouterDeps.ts similarity index 97% rename from packages/cli/src/modules/migrate/commands/reactRouterDeps.ts rename to packages/cli-module-migrate/src/commands/reactRouterDeps.ts index e5a12de3cd..802d958e61 100644 --- a/packages/cli/src/modules/migrate/commands/reactRouterDeps.ts +++ b/packages/cli-module-migrate/src/commands/reactRouterDeps.ts @@ -18,7 +18,7 @@ import { cli } from 'cleye'; import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; import { PackageGraph, PackageRoles } from '@backstage/cli-node'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; const REACT_ROUTER_DEPS = ['react-router', 'react-router-dom']; const REACT_ROUTER_RANGE = '6.0.0-beta.0 || ^6.3.0'; diff --git a/packages/cli/src/modules/migrate/commands/versions/bump.test.ts b/packages/cli-module-migrate/src/commands/versions/bump.test.ts similarity index 100% rename from packages/cli/src/modules/migrate/commands/versions/bump.test.ts rename to packages/cli-module-migrate/src/commands/versions/bump.test.ts diff --git a/packages/cli/src/modules/migrate/commands/versions/bump.ts b/packages/cli-module-migrate/src/commands/versions/bump.ts similarity index 99% rename from packages/cli/src/modules/migrate/commands/versions/bump.ts rename to packages/cli-module-migrate/src/commands/versions/bump.ts index 0142e63985..518126a3de 100644 --- a/packages/cli/src/modules/migrate/commands/versions/bump.ts +++ b/packages/cli-module-migrate/src/commands/versions/bump.ts @@ -48,7 +48,7 @@ import { import { migrateMovedPackages } from './migrate'; import { runYarnInstall } from '../../lib/utils'; import { run } from '@backstage/cli-common'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; const DEP_TYPES = [ 'dependencies', diff --git a/packages/cli/src/modules/migrate/commands/versions/migrate.test.ts b/packages/cli-module-migrate/src/commands/versions/migrate.test.ts similarity index 100% rename from packages/cli/src/modules/migrate/commands/versions/migrate.test.ts rename to packages/cli-module-migrate/src/commands/versions/migrate.test.ts diff --git a/packages/cli/src/modules/migrate/commands/versions/migrate.ts b/packages/cli-module-migrate/src/commands/versions/migrate.ts similarity index 98% rename from packages/cli/src/modules/migrate/commands/versions/migrate.ts rename to packages/cli-module-migrate/src/commands/versions/migrate.ts index eb0596d2af..a8ecb6cad4 100644 --- a/packages/cli/src/modules/migrate/commands/versions/migrate.ts +++ b/packages/cli-module-migrate/src/commands/versions/migrate.ts @@ -21,7 +21,7 @@ import { readJson, writeJson } from 'fs-extra'; import { minimatch } from 'minimatch'; import { runYarnInstall } from '../../lib/utils'; import replace from 'replace-in-file'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; declare module 'replace-in-file' { export default function (config: { diff --git a/packages/cli/src/modules/migrate/index.ts b/packages/cli-module-migrate/src/index.ts similarity index 98% rename from packages/cli/src/modules/migrate/index.ts rename to packages/cli-module-migrate/src/index.ts index ca77f678a4..e5d89383b8 100644 --- a/packages/cli/src/modules/migrate/index.ts +++ b/packages/cli-module-migrate/src/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { createCliModule } from '@backstage/cli-node'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export default createCliModule({ packageJson, diff --git a/packages/cli/src/modules/migrate/lib/utils.ts b/packages/cli-module-migrate/src/lib/utils.ts similarity index 100% rename from packages/cli/src/modules/migrate/lib/utils.ts rename to packages/cli-module-migrate/src/lib/utils.ts diff --git a/packages/cli/src/modules/migrate/lib/versioning/packages.test.ts b/packages/cli-module-migrate/src/lib/versioning/packages.test.ts similarity index 100% rename from packages/cli/src/modules/migrate/lib/versioning/packages.test.ts rename to packages/cli-module-migrate/src/lib/versioning/packages.test.ts diff --git a/packages/cli/src/modules/migrate/lib/versioning/packages.ts b/packages/cli-module-migrate/src/lib/versioning/packages.ts similarity index 100% rename from packages/cli/src/modules/migrate/lib/versioning/packages.ts rename to packages/cli-module-migrate/src/lib/versioning/packages.ts diff --git a/packages/cli/src/modules/migrate/lib/versioning/yarn.ts b/packages/cli-module-migrate/src/lib/versioning/yarn.ts similarity index 100% rename from packages/cli/src/modules/migrate/lib/versioning/yarn.ts rename to packages/cli-module-migrate/src/lib/versioning/yarn.ts diff --git a/packages/cli-module-new/.eslintrc.js b/packages/cli-module-new/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-new/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-new/catalog-info.yaml b/packages/cli-module-new/catalog-info.yaml new file mode 100644 index 0000000000..997f06d629 --- /dev/null +++ b/packages/cli-module-new/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-new + title: '@backstage/cli-module-new' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-new/package.json b/packages/cli-module-new/package.json new file mode 100644 index 0000000000..5a04becd22 --- /dev/null +++ b/packages/cli-module-new/package.json @@ -0,0 +1,39 @@ +{ + "name": "@backstage/cli-module-new", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-new" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-node": "workspace:^" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } +} diff --git a/packages/cli/src/modules/new/commands/new.test.ts b/packages/cli-module-new/src/commands/new.test.ts similarity index 96% rename from packages/cli/src/modules/new/commands/new.test.ts rename to packages/cli-module-new/src/commands/new.test.ts index 463add855d..54663ab60d 100644 --- a/packages/cli/src/modules/new/commands/new.test.ts +++ b/packages/cli-module-new/src/commands/new.test.ts @@ -16,7 +16,7 @@ import { createNewPackage } from '../lib/createNewPackage'; import { default as newCommand } from './new'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; jest.mock('../lib/createNewPackage'); diff --git a/packages/cli/src/modules/new/commands/new.ts b/packages/cli-module-new/src/commands/new.ts similarity index 98% rename from packages/cli/src/modules/new/commands/new.ts rename to packages/cli-module-new/src/commands/new.ts index 296a3a321e..3d7fcdf4e3 100644 --- a/packages/cli/src/modules/new/commands/new.ts +++ b/packages/cli-module-new/src/commands/new.ts @@ -16,7 +16,7 @@ import { cli } from 'cleye'; import { createNewPackage } from '../lib/createNewPackage'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { for (const flag of ['skipInstall', 'npmRegistry', 'baseVersion']) { diff --git a/packages/cli/src/modules/new/index.ts b/packages/cli-module-new/src/index.ts similarity index 97% rename from packages/cli/src/modules/new/index.ts rename to packages/cli-module-new/src/index.ts index 2a08a71e97..c9bc322083 100644 --- a/packages/cli/src/modules/new/index.ts +++ b/packages/cli-module-new/src/index.ts @@ -15,7 +15,7 @@ */ import { createCliModule } from '@backstage/cli-node'; import { NotImplementedError } from '@backstage/errors'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export default createCliModule({ packageJson, diff --git a/packages/cli/src/modules/new/lib/codeowners/codeowners.test.ts b/packages/cli-module-new/src/lib/codeowners/codeowners.test.ts similarity index 100% rename from packages/cli/src/modules/new/lib/codeowners/codeowners.test.ts rename to packages/cli-module-new/src/lib/codeowners/codeowners.test.ts diff --git a/packages/cli/src/modules/new/lib/codeowners/codeowners.ts b/packages/cli-module-new/src/lib/codeowners/codeowners.ts similarity index 100% rename from packages/cli/src/modules/new/lib/codeowners/codeowners.ts rename to packages/cli-module-new/src/lib/codeowners/codeowners.ts diff --git a/packages/cli/src/modules/new/lib/codeowners/index.ts b/packages/cli-module-new/src/lib/codeowners/index.ts similarity index 100% rename from packages/cli/src/modules/new/lib/codeowners/index.ts rename to packages/cli-module-new/src/lib/codeowners/index.ts diff --git a/packages/cli/src/modules/new/lib/createNewPackage.ts b/packages/cli-module-new/src/lib/createNewPackage.ts similarity index 100% rename from packages/cli/src/modules/new/lib/createNewPackage.ts rename to packages/cli-module-new/src/lib/createNewPackage.ts diff --git a/packages/cli/src/modules/new/lib/defaultTemplates.ts b/packages/cli-module-new/src/lib/defaultTemplates.ts similarity index 100% rename from packages/cli/src/modules/new/lib/defaultTemplates.ts rename to packages/cli-module-new/src/lib/defaultTemplates.ts diff --git a/packages/cli/src/modules/new/lib/execution/PortableTemplater.ts b/packages/cli-module-new/src/lib/execution/PortableTemplater.ts similarity index 100% rename from packages/cli/src/modules/new/lib/execution/PortableTemplater.ts rename to packages/cli-module-new/src/lib/execution/PortableTemplater.ts diff --git a/packages/cli/src/modules/new/lib/execution/executePortableTemplate.ts b/packages/cli-module-new/src/lib/execution/executePortableTemplate.ts similarity index 100% rename from packages/cli/src/modules/new/lib/execution/executePortableTemplate.ts rename to packages/cli-module-new/src/lib/execution/executePortableTemplate.ts diff --git a/packages/cli/src/modules/new/lib/execution/index.ts b/packages/cli-module-new/src/lib/execution/index.ts similarity index 100% rename from packages/cli/src/modules/new/lib/execution/index.ts rename to packages/cli-module-new/src/lib/execution/index.ts diff --git a/packages/cli/src/modules/new/lib/execution/installNewPackage.ts b/packages/cli-module-new/src/lib/execution/installNewPackage.ts similarity index 100% rename from packages/cli/src/modules/new/lib/execution/installNewPackage.ts rename to packages/cli-module-new/src/lib/execution/installNewPackage.ts diff --git a/packages/cli/src/modules/new/lib/execution/writeTemplateContents.test.ts b/packages/cli-module-new/src/lib/execution/writeTemplateContents.test.ts similarity index 100% rename from packages/cli/src/modules/new/lib/execution/writeTemplateContents.test.ts rename to packages/cli-module-new/src/lib/execution/writeTemplateContents.test.ts diff --git a/packages/cli/src/modules/new/lib/execution/writeTemplateContents.ts b/packages/cli-module-new/src/lib/execution/writeTemplateContents.ts similarity index 100% rename from packages/cli/src/modules/new/lib/execution/writeTemplateContents.ts rename to packages/cli-module-new/src/lib/execution/writeTemplateContents.ts diff --git a/packages/cli/src/modules/new/lib/preparation/collectPortableTemplateInput.test.ts b/packages/cli-module-new/src/lib/preparation/collectPortableTemplateInput.test.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/collectPortableTemplateInput.test.ts rename to packages/cli-module-new/src/lib/preparation/collectPortableTemplateInput.test.ts diff --git a/packages/cli/src/modules/new/lib/preparation/collectPortableTemplateInput.ts b/packages/cli-module-new/src/lib/preparation/collectPortableTemplateInput.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/collectPortableTemplateInput.ts rename to packages/cli-module-new/src/lib/preparation/collectPortableTemplateInput.ts diff --git a/packages/cli/src/modules/new/lib/preparation/index.ts b/packages/cli-module-new/src/lib/preparation/index.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/index.ts rename to packages/cli-module-new/src/lib/preparation/index.ts diff --git a/packages/cli/src/modules/new/lib/preparation/loadPortableTemplate.test.ts b/packages/cli-module-new/src/lib/preparation/loadPortableTemplate.test.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/loadPortableTemplate.test.ts rename to packages/cli-module-new/src/lib/preparation/loadPortableTemplate.test.ts diff --git a/packages/cli/src/modules/new/lib/preparation/loadPortableTemplate.ts b/packages/cli-module-new/src/lib/preparation/loadPortableTemplate.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/loadPortableTemplate.ts rename to packages/cli-module-new/src/lib/preparation/loadPortableTemplate.ts diff --git a/packages/cli/src/modules/new/lib/preparation/loadPortableTemplateConfig.test.ts b/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.test.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/loadPortableTemplateConfig.test.ts rename to packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.test.ts diff --git a/packages/cli/src/modules/new/lib/preparation/loadPortableTemplateConfig.ts b/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/loadPortableTemplateConfig.ts rename to packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.ts diff --git a/packages/cli/src/modules/new/lib/preparation/resolvePackageParams.test.ts b/packages/cli-module-new/src/lib/preparation/resolvePackageParams.test.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/resolvePackageParams.test.ts rename to packages/cli-module-new/src/lib/preparation/resolvePackageParams.test.ts diff --git a/packages/cli/src/modules/new/lib/preparation/resolvePackageParams.ts b/packages/cli-module-new/src/lib/preparation/resolvePackageParams.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/resolvePackageParams.ts rename to packages/cli-module-new/src/lib/preparation/resolvePackageParams.ts diff --git a/packages/cli/src/modules/new/lib/preparation/selectTemplateInteractively.test.ts b/packages/cli-module-new/src/lib/preparation/selectTemplateInteractively.test.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/selectTemplateInteractively.test.ts rename to packages/cli-module-new/src/lib/preparation/selectTemplateInteractively.test.ts diff --git a/packages/cli/src/modules/new/lib/preparation/selectTemplateInteractively.ts b/packages/cli-module-new/src/lib/preparation/selectTemplateInteractively.ts similarity index 100% rename from packages/cli/src/modules/new/lib/preparation/selectTemplateInteractively.ts rename to packages/cli-module-new/src/lib/preparation/selectTemplateInteractively.ts diff --git a/packages/cli/src/modules/new/lib/tasks.ts b/packages/cli-module-new/src/lib/tasks.ts similarity index 100% rename from packages/cli/src/modules/new/lib/tasks.ts rename to packages/cli-module-new/src/lib/tasks.ts diff --git a/packages/cli/src/modules/new/lib/types.ts b/packages/cli-module-new/src/lib/types.ts similarity index 100% rename from packages/cli/src/modules/new/lib/types.ts rename to packages/cli-module-new/src/lib/types.ts diff --git a/packages/cli/src/modules/new/lib/version.test.ts b/packages/cli-module-new/src/lib/version.test.ts similarity index 100% rename from packages/cli/src/modules/new/lib/version.test.ts rename to packages/cli-module-new/src/lib/version.test.ts diff --git a/packages/cli/src/modules/new/lib/version.ts b/packages/cli-module-new/src/lib/version.ts similarity index 63% rename from packages/cli/src/modules/new/lib/version.ts rename to packages/cli-module-new/src/lib/version.ts index 0849e8a9e8..57c5646a14 100644 --- a/packages/cli/src/modules/new/lib/version.ts +++ b/packages/cli-module-new/src/lib/version.ts @@ -30,28 +30,30 @@ This does not create an actual dependency on these packages and does not bring i Rollup will extract the value of the version field in each package at build time without leaving any imports in place. */ -import { version as backendPluginApi } from '../../../../../../packages/backend-plugin-api/package.json'; -import { version as backendTestUtils } from '../../../../../../packages/backend-test-utils/package.json'; -import { version as catalogClient } from '../../../../../../packages/catalog-client/package.json'; -import { version as cli } from '../../../../../../packages/cli/package.json'; -import { version as config } from '../../../../../../packages/config/package.json'; -import { version as coreAppApi } from '../../../../../../packages/core-app-api/package.json'; -import { version as coreComponents } from '../../../../../../packages/core-components/package.json'; -import { version as corePluginApi } from '../../../../../../packages/core-plugin-api/package.json'; -import { version as devUtils } from '../../../../../../packages/dev-utils/package.json'; -import { version as errors } from '../../../../../../packages/errors/package.json'; -import { version as frontendDefaults } from '../../../../../../packages/frontend-defaults/package.json'; -import { version as frontendPluginApi } from '../../../../../../packages/frontend-plugin-api/package.json'; -import { version as frontendTestUtils } from '../../../../../../packages/frontend-test-utils/package.json'; -import { version as testUtils } from '../../../../../../packages/test-utils/package.json'; -import { version as scaffolderNode } from '../../../../../../plugins/scaffolder-node/package.json'; -import { version as scaffolderNodeTestUtils } from '../../../../../../plugins/scaffolder-node-test-utils/package.json'; -import { version as authBackend } from '../../../../../../plugins/auth-backend/package.json'; -import { version as authBackendModuleGuestProvider } from '../../../../../../plugins/auth-backend-module-guest-provider/package.json'; -import { version as catalogNode } from '../../../../../../plugins/catalog-node/package.json'; -import { version as theme } from '../../../../../../packages/theme/package.json'; -import { version as types } from '../../../../../../packages/types/package.json'; -import { version as backendDefaults } from '../../../../../../packages/backend-defaults/package.json'; +type Pkg = { version: string }; +const v = (path: string) => (require(path) as Pkg).version; +const backendPluginApi = v('../../../backend-plugin-api/package.json'); +const backendTestUtils = v('../../../backend-test-utils/package.json'); +const catalogClient = v('../../../catalog-client/package.json'); +const cli = v('../../../cli/package.json'); +const config = v('../../../config/package.json'); +const coreAppApi = v('../../../core-app-api/package.json'); +const coreComponents = v('../../../core-components/package.json'); +const corePluginApi = v('../../../core-plugin-api/package.json'); +const devUtils = v('../../../dev-utils/package.json'); +const errors = v('../../../errors/package.json'); +const frontendDefaults = v('../../../frontend-defaults/package.json'); +const frontendPluginApi = v('../../../frontend-plugin-api/package.json'); +const frontendTestUtils = v('../../../frontend-test-utils/package.json'); +const testUtils = v('../../../test-utils/package.json'); +const scaffolderNode = v('../../../../plugins/scaffolder-node/package.json'); +const scaffolderNodeTestUtils = v('../../../../plugins/scaffolder-node-test-utils/package.json'); +const authBackend = v('../../../../plugins/auth-backend/package.json'); +const authBackendModuleGuestProvider = v('../../../../plugins/auth-backend-module-guest-provider/package.json'); +const catalogNode = v('../../../../plugins/catalog-node/package.json'); +const theme = v('../../../theme/package.json'); +const types = v('../../../types/package.json'); +const backendDefaults = v('../../../backend-defaults/package.json'); export const packageVersions: Record = { '@backstage/backend-defaults': backendDefaults, diff --git a/packages/cli-module-test-jest/.eslintrc.js b/packages/cli-module-test-jest/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-test-jest/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-test-jest/catalog-info.yaml b/packages/cli-module-test-jest/catalog-info.yaml new file mode 100644 index 0000000000..c928c628f5 --- /dev/null +++ b/packages/cli-module-test-jest/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-test-jest + title: '@backstage/cli-module-test-jest' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-test-jest/package.json b/packages/cli-module-test-jest/package.json new file mode 100644 index 0000000000..7df933dee9 --- /dev/null +++ b/packages/cli-module-test-jest/package.json @@ -0,0 +1,39 @@ +{ + "name": "@backstage/cli-module-test-jest", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-test-jest" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-node": "workspace:^" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } +} diff --git a/packages/cli/src/modules/test/commands/package/test.ts b/packages/cli-module-test-jest/src/commands/package/test.ts similarity index 94% rename from packages/cli/src/modules/test/commands/package/test.ts rename to packages/cli-module-test-jest/src/commands/package/test.ts index b57ae909be..035db8272f 100644 --- a/packages/cli/src/modules/test/commands/package/test.ts +++ b/packages/cli-module-test-jest/src/commands/package/test.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { runCheck, findOwnPaths } from '@backstage/cli-common'; -import type { CliCommandContext } from '../../../../wiring/types'; +import { runCheck } from '@backstage/cli-common'; +import type { CliCommandContext } from '@backstage/cli-node'; function includesAnyOf(hayStack: string[], ...needles: string[]) { for (const needle of needles) { @@ -30,7 +30,7 @@ export default async ({ args }: CliCommandContext) => { // Only include our config if caller isn't passing their own config if (!includesAnyOf(args, '-c', '--config')) { /* eslint-disable-next-line no-restricted-syntax */ - args.push('--config', findOwnPaths(__dirname).resolve('config/jest.js')); + args.push('--config', require.resolve('@backstage/cli/config/jest')); } if (!includesAnyOf(args, '--no-passWithNoTests', '--passWithNoTests=false')) { diff --git a/packages/cli/src/modules/test/commands/repo/test.test.ts b/packages/cli-module-test-jest/src/commands/repo/test.test.ts similarity index 100% rename from packages/cli/src/modules/test/commands/repo/test.test.ts rename to packages/cli-module-test-jest/src/commands/repo/test.test.ts diff --git a/packages/cli/src/modules/test/commands/repo/test.ts b/packages/cli-module-test-jest/src/commands/repo/test.ts similarity index 98% rename from packages/cli/src/modules/test/commands/repo/test.ts rename to packages/cli-module-test-jest/src/commands/repo/test.ts index adcaf99dfd..e45df2bcfc 100644 --- a/packages/cli/src/modules/test/commands/repo/test.ts +++ b/packages/cli-module-test-jest/src/commands/repo/test.ts @@ -28,10 +28,9 @@ import { runCheck, runOutput, targetPaths, - findOwnPaths, isChildPath, } from '@backstage/cli-common'; -import type { CliCommandContext } from '../../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; type JestProject = { displayName: string; @@ -182,7 +181,7 @@ export default async ({ args, info }: CliCommandContext) => { // Only include our config if caller isn't passing their own config if (!hasFlags('-c', '--config')) { /* eslint-disable-next-line no-restricted-syntax */ - args.push('--config', findOwnPaths(__dirname).resolve('config/jest.js')); + args.push('--config', require.resolve('@backstage/cli/config/jest')); } if (!hasFlags('--passWithNoTests')) { diff --git a/packages/cli/src/modules/test/index.ts b/packages/cli-module-test-jest/src/index.ts similarity index 96% rename from packages/cli/src/modules/test/index.ts rename to packages/cli-module-test-jest/src/index.ts index f10e13828f..b2060fa89e 100644 --- a/packages/cli/src/modules/test/index.ts +++ b/packages/cli-module-test-jest/src/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { createCliModule } from '@backstage/cli-node'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export default createCliModule({ packageJson, diff --git a/packages/cli-module-translations/.eslintrc.js b/packages/cli-module-translations/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-module-translations/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-module-translations/catalog-info.yaml b/packages/cli-module-translations/catalog-info.yaml new file mode 100644 index 0000000000..a2f21fc649 --- /dev/null +++ b/packages/cli-module-translations/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-module-translations + title: '@backstage/cli-module-translations' + description: CLI module for Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-module-translations/package.json b/packages/cli-module-translations/package.json new file mode 100644 index 0000000000..8818ff32d4 --- /dev/null +++ b/packages/cli-module-translations/package.json @@ -0,0 +1,39 @@ +{ + "name": "@backstage/cli-module-translations", + "version": "0.1.0", + "description": "CLI module for Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-module-translations" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/cli-node": "workspace:^" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } +} diff --git a/packages/cli/src/modules/translations/commands/export.ts b/packages/cli-module-translations/src/commands/export.ts similarity index 98% rename from packages/cli/src/modules/translations/commands/export.ts rename to packages/cli-module-translations/src/commands/export.ts index ca496ad859..a1d2eb2dae 100644 --- a/packages/cli/src/modules/translations/commands/export.ts +++ b/packages/cli-module-translations/src/commands/export.ts @@ -33,7 +33,7 @@ import { formatMessagePath, validatePattern, } from '../lib/messageFilePath'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; export default async ({ args, info }: CliCommandContext) => { const { diff --git a/packages/cli/src/modules/translations/commands/import.ts b/packages/cli-module-translations/src/commands/import.ts similarity index 99% rename from packages/cli/src/modules/translations/commands/import.ts rename to packages/cli-module-translations/src/commands/import.ts index 0e27321da5..35a071c4fb 100644 --- a/packages/cli/src/modules/translations/commands/import.ts +++ b/packages/cli-module-translations/src/commands/import.ts @@ -28,7 +28,7 @@ import { createMessagePathParser, formatMessagePath, } from '../lib/messageFilePath'; -import type { CliCommandContext } from '../../../wiring/types'; +import type { CliCommandContext } from '@backstage/cli-node'; interface ManifestRefEntry { package: string; diff --git a/packages/cli/src/modules/translations/index.ts b/packages/cli-module-translations/src/index.ts similarity index 96% rename from packages/cli/src/modules/translations/index.ts rename to packages/cli-module-translations/src/index.ts index 7654c2e0b6..e075dc61ae 100644 --- a/packages/cli/src/modules/translations/index.ts +++ b/packages/cli-module-translations/src/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { createCliModule } from '@backstage/cli-node'; -import packageJson from '../../../package.json'; +import packageJson from '../package.json'; export default createCliModule({ packageJson, diff --git a/packages/cli/src/modules/translations/lib/discoverPackages.ts b/packages/cli-module-translations/src/lib/discoverPackages.ts similarity index 100% rename from packages/cli/src/modules/translations/lib/discoverPackages.ts rename to packages/cli-module-translations/src/lib/discoverPackages.ts diff --git a/packages/cli/src/modules/translations/lib/extractTranslations.test.ts b/packages/cli-module-translations/src/lib/extractTranslations.test.ts similarity index 100% rename from packages/cli/src/modules/translations/lib/extractTranslations.test.ts rename to packages/cli-module-translations/src/lib/extractTranslations.test.ts diff --git a/packages/cli/src/modules/translations/lib/extractTranslations.ts b/packages/cli-module-translations/src/lib/extractTranslations.ts similarity index 100% rename from packages/cli/src/modules/translations/lib/extractTranslations.ts rename to packages/cli-module-translations/src/lib/extractTranslations.ts diff --git a/packages/cli/src/modules/translations/lib/messageFilePath.test.ts b/packages/cli-module-translations/src/lib/messageFilePath.test.ts similarity index 100% rename from packages/cli/src/modules/translations/lib/messageFilePath.test.ts rename to packages/cli-module-translations/src/lib/messageFilePath.test.ts diff --git a/packages/cli/src/modules/translations/lib/messageFilePath.ts b/packages/cli-module-translations/src/lib/messageFilePath.ts similarity index 100% rename from packages/cli/src/modules/translations/lib/messageFilePath.ts rename to packages/cli-module-translations/src/lib/messageFilePath.ts diff --git a/packages/cli/package.json b/packages/cli/package.json index 8e03c60d0f..189fd8faaa 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -49,6 +49,17 @@ "dependencies": { "@backstage/catalog-model": "workspace:^", "@backstage/cli-common": "workspace:^", + "@backstage/cli-module-auth": "workspace:^", + "@backstage/cli-module-build": "workspace:^", + "@backstage/cli-module-config": "workspace:^", + "@backstage/cli-module-create-github-app": "workspace:^", + "@backstage/cli-module-info": "workspace:^", + "@backstage/cli-module-lint": "workspace:^", + "@backstage/cli-module-maintenance": "workspace:^", + "@backstage/cli-module-migrate": "workspace:^", + "@backstage/cli-module-new": "workspace:^", + "@backstage/cli-module-test-jest": "workspace:^", + "@backstage/cli-module-translations": "workspace:^", "@backstage/cli-node": "workspace:^", "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 14da5e791e..8773c3b112 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -18,16 +18,16 @@ import { CliInitializer } from './wiring/CliInitializer'; (async () => { const initializer = new CliInitializer(); - initializer.add(import('./modules/build')); - initializer.add(import('./modules/config')); - initializer.add(import('./modules/create-github-app')); - initializer.add(import('./modules/info')); - initializer.add(import('./modules/lint')); - initializer.add(import('./modules/maintenance')); - initializer.add(import('./modules/migrate')); - initializer.add(import('./modules/new')); - initializer.add(import('./modules/test')); - initializer.add(import('./modules/translations')); - initializer.add(import('./modules/auth')); + initializer.add(import('@backstage/cli-module-build')); + initializer.add(import('@backstage/cli-module-config')); + initializer.add(import('@backstage/cli-module-create-github-app')); + initializer.add(import('@backstage/cli-module-info')); + initializer.add(import('@backstage/cli-module-lint')); + initializer.add(import('@backstage/cli-module-maintenance')); + initializer.add(import('@backstage/cli-module-migrate')); + initializer.add(import('@backstage/cli-module-new')); + initializer.add(import('@backstage/cli-module-test-jest')); + initializer.add(import('@backstage/cli-module-translations')); + initializer.add(import('@backstage/cli-module-auth')); await initializer.run(); })(); diff --git a/yarn.lock b/yarn.lock index 7465a75f4d..98d39db148 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2801,6 +2801,221 @@ __metadata: languageName: unknown linkType: soft +"@backstage/cli-module-auth@workspace:^, @backstage/cli-module-auth@workspace:packages/cli-module-auth": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-auth@workspace:packages/cli-module-auth" + dependencies: + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/cli-node": "workspace:^" + "@backstage/errors": "workspace:^" + "@types/fs-extra": "npm:^11.0.0" + "@types/proper-lockfile": "npm:^4" + cleye: "npm:^2.3.0" + cross-fetch: "npm:^4.0.0" + fs-extra: "npm:^11.2.0" + glob: "npm:^7.1.7" + inquirer: "npm:^8.2.0" + proper-lockfile: "npm:^4.1.2" + yaml: "npm:^2.0.0" + zod: "npm:^3.25.76" + languageName: unknown + linkType: soft + +"@backstage/cli-module-build@workspace:^, @backstage/cli-module-build@workspace:packages/cli-module-build": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-build@workspace:packages/cli-module-build" + dependencies: + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" + "@backstage/cli-node": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/config-loader": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/module-federation-common": "workspace:^" + "@manypkg/get-packages": "npm:^1.1.3" + "@module-federation/enhanced": "npm:^0.21.6" + "@pmmmwh/react-refresh-webpack-plugin": "npm:^0.6.2" + "@rollup/plugin-commonjs": "npm:^26.0.0" + "@rollup/plugin-json": "npm:^6.0.0" + "@rollup/plugin-node-resolve": "npm:^15.0.0" + "@rollup/plugin-yaml": "npm:^4.0.0" + "@rspack/core": "npm:^1.4.11" + "@rspack/dev-server": "npm:^1.1.4" + "@rspack/plugin-react-refresh": "npm:^1.4.3" + "@types/fs-extra": "npm:^11.0.0" + "@types/lodash": "npm:^4.14.151" + "@types/npm-packlist": "npm:^3.0.0" + "@types/shell-quote": "npm:^1.7.5" + bfj: "npm:^9.0.2" + chalk: "npm:^4.0.0" + chokidar: "npm:^3.5.3" + cleye: "npm:^2.3.0" + cross-spawn: "npm:^7.0.6" + ctrlc-windows: "npm:^2.1.0" + esbuild-loader: "npm:^4.4.2" + eslint-rspack-plugin: "npm:^4.2.1" + eslint-webpack-plugin: "npm:^5.0.3" + fork-ts-checker-webpack-plugin: "npm:^9.1.0" + fs-extra: "npm:^11.2.0" + glob: "npm:^7.1.7" + html-webpack-plugin: "npm:^5.6.3" + lodash: "npm:^4.17.21" + mini-css-extract-plugin: "npm:^2.10.1" + node-stdlib-browser: "npm:^1.3.1" + npm-packlist: "npm:^5.0.0" + p-queue: "npm:^6.6.2" + postcss: "npm:^8.1.0" + postcss-import: "npm:^16.1.0" + react-dev-utils: "npm:^12.0.0-next.60" + rollup: "npm:^4.59.0" + rollup-plugin-dts: "npm:^6.1.0" + rollup-plugin-esbuild: "npm:^6.1.1" + rollup-plugin-postcss: "npm:^4.0.0" + rollup-pluginutils: "npm:^2.8.2" + shell-quote: "npm:^1.8.1" + tar: "npm:^7.5.6" + ts-checker-rspack-plugin: "npm:^1.1.5" + ts-morph: "npm:^24.0.0" + webpack: "npm:^5.105.4" + webpack-dev-server: "npm:^5.2.3" + yn: "npm:^4.0.0" + languageName: unknown + linkType: soft + +"@backstage/cli-module-config@workspace:^, @backstage/cli-module-config@workspace:packages/cli-module-config": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-config@workspace:packages/cli-module-config" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" + "@backstage/cli-node": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/config-loader": "workspace:^" + "@backstage/types": "workspace:^" + "@manypkg/get-packages": "npm:^1.1.3" + "@types/json-schema": "npm:^7.0.6" + chalk: "npm:^4.0.0" + cleye: "npm:^2.3.0" + json-schema: "npm:^0.4.0" + react-dev-utils: "npm:^12.0.0-next.60" + yaml: "npm:^2.0.0" + languageName: unknown + linkType: soft + +"@backstage/cli-module-create-github-app@workspace:^, @backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" + "@backstage/cli-node": "workspace:^" + "@octokit/request": "npm:^8.0.0" + "@types/express": "npm:^4.17.6" + "@types/fs-extra": "npm:^11.0.0" + chalk: "npm:^4.0.0" + cleye: "npm:^2.3.0" + express: "npm:^4.22.0" + fs-extra: "npm:^11.2.0" + inquirer: "npm:^8.2.0" + react-dev-utils: "npm:^12.0.0-next.60" + yaml: "npm:^2.0.0" + languageName: unknown + linkType: soft + +"@backstage/cli-module-info@workspace:^, @backstage/cli-module-info@workspace:packages/cli-module-info": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-info@workspace:packages/cli-module-info" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" + "@backstage/cli-node": "workspace:^" + "@types/fs-extra": "npm:^11.0.0" + cleye: "npm:^2.3.0" + fs-extra: "npm:^11.2.0" + minimatch: "npm:^10.2.1" + languageName: unknown + linkType: soft + +"@backstage/cli-module-lint@workspace:^, @backstage/cli-module-lint@workspace:packages/cli-module-lint": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-lint@workspace:packages/cli-module-lint" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" + "@backstage/cli-node": "workspace:^" + "@types/fs-extra": "npm:^11.0.0" + "@types/shell-quote": "npm:^1.7.5" + chalk: "npm:^4.0.0" + cleye: "npm:^2.3.0" + eslint: "npm:^8.6.0" + fs-extra: "npm:^11.2.0" + globby: "npm:^11.0.0" + shell-quote: "npm:^1.8.1" + languageName: unknown + linkType: soft + +"@backstage/cli-module-maintenance@workspace:^, @backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" + "@backstage/cli-node": "workspace:^" + "@types/fs-extra": "npm:^11.0.0" + chalk: "npm:^4.0.0" + cleye: "npm:^2.3.0" + eslint: "npm:^8.6.0" + fs-extra: "npm:^11.2.0" + languageName: unknown + linkType: soft + +"@backstage/cli-module-migrate@workspace:^, @backstage/cli-module-migrate@workspace:packages/cli-module-migrate": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-migrate@workspace:packages/cli-module-migrate" + dependencies: + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" + "@backstage/cli-node": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@manypkg/get-packages": "npm:^1.1.3" + "@types/fs-extra": "npm:^11.0.0" + cleye: "npm:^2.3.0" + fs-extra: "npm:^11.2.0" + msw: "npm:^1.0.0" + languageName: unknown + linkType: soft + +"@backstage/cli-module-new@workspace:^, @backstage/cli-module-new@workspace:packages/cli-module-new": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-new@workspace:packages/cli-module-new" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-node": "workspace:^" + languageName: unknown + linkType: soft + +"@backstage/cli-module-test-jest@workspace:^, @backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-node": "workspace:^" + languageName: unknown + linkType: soft + +"@backstage/cli-module-translations@workspace:^, @backstage/cli-module-translations@workspace:packages/cli-module-translations": + version: 0.0.0-use.local + resolution: "@backstage/cli-module-translations@workspace:packages/cli-module-translations" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-node": "workspace:^" + languageName: unknown + linkType: soft + "@backstage/cli-node@workspace:^, @backstage/cli-node@workspace:packages/cli-node": version: 0.0.0-use.local resolution: "@backstage/cli-node@workspace:packages/cli-node" @@ -2831,6 +3046,17 @@ __metadata: "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli-common": "workspace:^" + "@backstage/cli-module-auth": "workspace:^" + "@backstage/cli-module-build": "workspace:^" + "@backstage/cli-module-config": "workspace:^" + "@backstage/cli-module-create-github-app": "workspace:^" + "@backstage/cli-module-info": "workspace:^" + "@backstage/cli-module-lint": "workspace:^" + "@backstage/cli-module-maintenance": "workspace:^" + "@backstage/cli-module-migrate": "workspace:^" + "@backstage/cli-module-new": "workspace:^" + "@backstage/cli-module-test-jest": "workspace:^" + "@backstage/cli-module-translations": "workspace:^" "@backstage/cli-node": "workspace:^" "@backstage/config": "workspace:^" "@backstage/config-loader": "workspace:^" @@ -14337,144 +14563,144 @@ __metadata: languageName: node linkType: hard -"@oxc-resolver/binding-android-arm-eabi@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.19.1" +"@oxc-resolver/binding-android-arm-eabi@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.16.3" conditions: os=android & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-android-arm64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-android-arm64@npm:11.19.1" +"@oxc-resolver/binding-android-arm64@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-android-arm64@npm:11.16.3" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-darwin-arm64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.19.1" +"@oxc-resolver/binding-darwin-arm64@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.16.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-darwin-x64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-darwin-x64@npm:11.19.1" +"@oxc-resolver/binding-darwin-x64@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-darwin-x64@npm:11.16.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-freebsd-x64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.19.1" +"@oxc-resolver/binding-freebsd-x64@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.16.3" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.19.1" +"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.3" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.19.1" +"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.3" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.19.1" +"@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.3" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-musl@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.19.1" +"@oxc-resolver/binding-linux-arm64-musl@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.16.3" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.19.1" +"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.3" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.19.1" +"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.3" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-riscv64-musl@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.19.1" +"@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.3" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-linux-s390x-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.19.1" +"@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.3" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.19.1" +"@oxc-resolver/binding-linux-x64-gnu@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.16.3" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-musl@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.19.1" +"@oxc-resolver/binding-linux-x64-musl@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.16.3" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-openharmony-arm64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.19.1" +"@oxc-resolver/binding-openharmony-arm64@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.16.3" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-wasm32-wasi@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.19.1" +"@oxc-resolver/binding-wasm32-wasi@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.16.3" dependencies: "@napi-rs/wasm-runtime": "npm:^1.1.1" conditions: cpu=wasm32 languageName: node linkType: hard -"@oxc-resolver/binding-win32-arm64-msvc@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.19.1" +"@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-win32-ia32-msvc@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.19.1" +"@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.3" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@oxc-resolver/binding-win32-x64-msvc@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.19.1" +"@oxc-resolver/binding-win32-x64-msvc@npm:11.16.3": + version: 11.16.3 + resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.16.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -14658,7 +14884,7 @@ __metadata: languageName: node linkType: hard -"@pmmmwh/react-refresh-webpack-plugin@npm:^0.6.0": +"@pmmmwh/react-refresh-webpack-plugin@npm:^0.6.0, @pmmmwh/react-refresh-webpack-plugin@npm:^0.6.2": version: 0.6.2 resolution: "@pmmmwh/react-refresh-webpack-plugin@npm:0.6.2" dependencies: @@ -17287,156 +17513,177 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.53.3" +"@rollup/rollup-android-arm-eabi@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.59.0" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-android-arm64@npm:4.53.3" +"@rollup/rollup-android-arm64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-android-arm64@npm:4.59.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-darwin-arm64@npm:4.53.3" +"@rollup/rollup-darwin-arm64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-darwin-arm64@npm:4.59.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-darwin-x64@npm:4.53.3" +"@rollup/rollup-darwin-x64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-darwin-x64@npm:4.59.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-freebsd-arm64@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.53.3" +"@rollup/rollup-freebsd-arm64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.59.0" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-freebsd-x64@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-freebsd-x64@npm:4.53.3" +"@rollup/rollup-freebsd-x64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-freebsd-x64@npm:4.59.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.53.3" +"@rollup/rollup-linux-arm-gnueabihf@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.59.0" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm-musleabihf@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.53.3" +"@rollup/rollup-linux-arm-musleabihf@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.59.0" conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.53.3" +"@rollup/rollup-linux-arm64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.59.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.53.3" +"@rollup/rollup-linux-arm64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.59.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-loong64-gnu@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.53.3" +"@rollup/rollup-linux-loong64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.59.0" conditions: os=linux & cpu=loong64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-ppc64-gnu@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.53.3" +"@rollup/rollup-linux-loong64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-loong64-musl@npm:4.59.0" + conditions: os=linux & cpu=loong64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-ppc64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.59.0" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.53.3" +"@rollup/rollup-linux-ppc64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.59.0" + conditions: os=linux & cpu=ppc64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.59.0" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-musl@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.53.3" +"@rollup/rollup-linux-riscv64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.59.0" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-s390x-gnu@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.53.3" +"@rollup/rollup-linux-s390x-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.59.0" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.53.3" +"@rollup/rollup-linux-x64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.59.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.53.3" +"@rollup/rollup-linux-x64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.59.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-openharmony-arm64@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-openharmony-arm64@npm:4.53.3" +"@rollup/rollup-openbsd-x64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-openbsd-x64@npm:4.59.0" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-openharmony-arm64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-openharmony-arm64@npm:4.59.0" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.53.3" +"@rollup/rollup-win32-arm64-msvc@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.59.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.53.3" +"@rollup/rollup-win32-ia32-msvc@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.59.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-gnu@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-win32-x64-gnu@npm:4.53.3" +"@rollup/rollup-win32-x64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-win32-x64-gnu@npm:4.59.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.53.3": - version: 4.53.3 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.53.3" +"@rollup/rollup-win32-x64-msvc@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.59.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -18965,8 +19212,8 @@ __metadata: linkType: hard "@snyk/dep-graph@npm:^2.12.0": - version: 2.14.0 - resolution: "@snyk/dep-graph@npm:2.14.0" + version: 2.16.3 + resolution: "@snyk/dep-graph@npm:2.16.3" dependencies: event-loop-spinner: "npm:^2.1.0" lodash.clone: "npm:^4.5.0" @@ -18987,7 +19234,7 @@ __metadata: packageurl-js: "npm:2.0.1" semver: "npm:^7.0.0" tslib: "npm:^2" - checksum: 10/e51882a2e566030a135d2fff477afbc7e4f8a14946089598fe56dd1e9b1b65fffe1ef8b3c8e2ff42629fc01d79b6d5dfeca1c505413731866c5b730728aee0a4 + checksum: 10/609c7946d0f64d4df4e68a3b5e2a61e5739f8b5dc57b42036f1651694fa1cc8d1537bb0e4a9a437a9fcd08c9b5db9d313c4c59a7e1267fb42993a9f41e78e2c6 languageName: node linkType: hard @@ -21185,7 +21432,17 @@ __metadata: languageName: node linkType: hard -"@types/eslint@npm:*, @types/eslint@npm:^8.56.10": +"@types/eslint@npm:*, @types/eslint@npm:^9.6.1": + version: 9.6.1 + resolution: "@types/eslint@npm:9.6.1" + dependencies: + "@types/estree": "npm:*" + "@types/json-schema": "npm:*" + checksum: 10/719fcd255760168a43d0e306ef87548e1e15bffe361d5f4022b0f266575637acc0ecb85604ac97879ee8ae83c6a6d0613b0ed31d0209ddf22a0fe6d608fc56fe + languageName: node + linkType: hard + +"@types/eslint@npm:^8.56.10": version: 8.56.12 resolution: "@types/eslint@npm:8.56.12" dependencies: @@ -22842,9 +23099,9 @@ __metadata: languageName: node linkType: hard -"@uiw/codemirror-extensions-basic-setup@npm:4.25.8": - version: 4.25.8 - resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.25.8" +"@uiw/codemirror-extensions-basic-setup@npm:4.25.4": + version: 4.25.4 + resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.25.4" dependencies: "@codemirror/autocomplete": "npm:^6.0.0" "@codemirror/commands": "npm:^6.0.0" @@ -22861,19 +23118,19 @@ __metadata: "@codemirror/search": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 10/a8d83465f9f3393b6e95d98ae7f3616ad57f819bce64224831d3db19647524538fc013973074a63551afa69daad9a8ab05f2e5c7441db7e30e722495d7e991d3 + checksum: 10/8fa523af7cb4ea36db5263221e5a34ecbf18e57ee5c57fbb46f7bfd08ff08523b9fe2c5ae376117d98edaa1a904d1a2966123710e0d866a78ec2d1359955773c languageName: node linkType: hard "@uiw/react-codemirror@npm:^4.9.3": - version: 4.25.8 - resolution: "@uiw/react-codemirror@npm:4.25.8" + version: 4.25.4 + resolution: "@uiw/react-codemirror@npm:4.25.4" dependencies: "@babel/runtime": "npm:^7.18.6" "@codemirror/commands": "npm:^6.1.0" "@codemirror/state": "npm:^6.1.1" "@codemirror/theme-one-dark": "npm:^6.0.0" - "@uiw/codemirror-extensions-basic-setup": "npm:4.25.8" + "@uiw/codemirror-extensions-basic-setup": "npm:4.25.4" codemirror: "npm:^6.0.0" peerDependencies: "@babel/runtime": ">=7.11.0" @@ -22883,7 +23140,7 @@ __metadata: codemirror: ">=6.0.0" react: ">=17.0.0" react-dom: ">=17.0.0" - checksum: 10/8c974e22dad1ad6231f33f7db42cd5b68caaf9bea545539b06b8a89dda3427eebadf47c8f48ee0d74cdf5a25000a8fcc02bac9fe560b624955eedf1f9bb47a85 + checksum: 10/679966cfa5cc2e7d5b7c8b40060018bebfc3a2d66492672c64e659e1c719cedd7a10ed7fb3aa014d77c42927581c4ebdf6760ab56568225781798b35dc13b8c6 languageName: node linkType: hard @@ -24652,7 +24909,14 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1, ansi-styles@npm:^6.2.3": +"ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: 10/70fdf883b704d17a5dfc9cde206e698c16bcd74e7f196ab821511651aee4f9f76c9514bdfa6ca3a27b5e49138b89cb222a28caf3afe4567570139577f991df32 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.2.3": version: 6.2.3 resolution: "ansi-styles@npm:6.2.3" checksum: 10/c49dad7639f3e48859bd51824c93b9eb0db628afc243c51c3dd2410c4a15ede1a83881c6c7341aa2b159c4f90c11befb38f2ba848c07c66c9f9de4bcd7cb9f30 @@ -29955,7 +30219,7 @@ __metadata: languageName: node linkType: hard -"esbuild-loader@npm:^4.0.0": +"esbuild-loader@npm:^4.0.0, esbuild-loader@npm:^4.4.2": version: 4.4.2 resolution: "esbuild-loader@npm:4.4.2" dependencies: @@ -30430,6 +30694,23 @@ __metadata: languageName: node linkType: hard +"eslint-webpack-plugin@npm:^5.0.3": + version: 5.0.3 + resolution: "eslint-webpack-plugin@npm:5.0.3" + dependencies: + "@types/eslint": "npm:^9.6.1" + flatted: "npm:^3.3.3" + jest-worker: "npm:^29.7.0" + micromatch: "npm:^4.0.8" + normalize-path: "npm:^3.0.0" + schema-utils: "npm:^4.3.2" + peerDependencies: + eslint: ^8.0.0 || ^9.0.0 + webpack: ^5.0.0 + checksum: 10/fbf86752ad9493ea70ef025a044c1437e105be51c430762ceac9ae930f4e67c9027d7b1b848969fb3abd285e32ce0fd04382d6e8326958be6b1068415bdd38ab + languageName: node + linkType: hard + "eslint@npm:^8.33.0, eslint@npm:^8.6.0": version: 8.57.1 resolution: "eslint@npm:8.57.1" @@ -31012,13 +31293,13 @@ __metadata: linkType: hard "express-rate-limit@npm:^8.2.1, express-rate-limit@npm:^8.2.2": - version: 8.3.1 - resolution: "express-rate-limit@npm:8.3.1" + version: 8.3.0 + resolution: "express-rate-limit@npm:8.3.0" dependencies: ip-address: "npm:10.1.0" peerDependencies: express: ">= 4.11" - checksum: 10/dd97bfc48c01a6d4c5433203232b5e7a1e55e21322bde49033e5f8c4339584fe671a94096144a0810f4ea21dcec8aaaf15823109627e609f8ed1bc5912a345cf + checksum: 10/e896a66fecc10639e65873186fdfb71f19d6af650220eb7ea5450725215c3eed8dc6ddcfa1e68a9db8c9facc3326fbc281512ad3ccd8f107f42a2466ce12c18c languageName: node linkType: hard @@ -31687,7 +31968,7 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^3.1.0, flatted@npm:^3.2.7, flatted@npm:^3.3.4": +"flatted@npm:^3.1.0, flatted@npm:^3.2.7, flatted@npm:^3.3.3, flatted@npm:^3.3.4": version: 3.4.1 resolution: "flatted@npm:3.4.1" checksum: 10/39a308e2ef82d2d8c80ebc74b67d4ff3f668be168137b649440b6735eb9c115d1e0c13ab0d9958b3d2ea9c85087ab7e14c14aa6f625a22b2916d89bbd91bc4a0 @@ -31787,7 +32068,7 @@ __metadata: languageName: node linkType: hard -"fork-ts-checker-webpack-plugin@npm:^9.0.0": +"fork-ts-checker-webpack-plugin@npm:^9.0.0, fork-ts-checker-webpack-plugin@npm:^9.1.0": version: 9.1.0 resolution: "fork-ts-checker-webpack-plugin@npm:9.1.0" dependencies: @@ -32290,7 +32571,14 @@ __metadata: languageName: node linkType: hard -"get-east-asian-width@npm:^1.0.0, get-east-asian-width@npm:^1.3.1, get-east-asian-width@npm:^1.5.0": +"get-east-asian-width@npm:^1.0.0": + version: 1.2.0 + resolution: "get-east-asian-width@npm:1.2.0" + checksum: 10/c9b280e7c7c67fb89fa17e867c4a9d1c9f1321aba2a9ee27bff37fb6ca9552bccda328c70a80c1f83a0e39ba1b7e3427e60f47823402d19e7a41b83417ec047a + languageName: node + linkType: hard + +"get-east-asian-width@npm:^1.3.1, get-east-asian-width@npm:^1.5.0": version: 1.5.0 resolution: "get-east-asian-width@npm:1.5.0" checksum: 10/60bc34cd1e975055ab99f0f177e31bed3e516ff7cee9c536474383954a976abaa6b94a51d99ad158ef1e372790fa096cab7d07f166bb0778f6587954c0fbe946 @@ -32677,13 +32965,20 @@ __metadata: languageName: node linkType: hard -"globals@npm:^17.0.0, globals@npm:^17.3.0": +"globals@npm:^17.0.0": version: 17.4.0 resolution: "globals@npm:17.4.0" checksum: 10/ffad244617e94efcb3da72b7beefc941167c21316148ce378f322db7af72db06468f370e23224b3c7b17b5173a7c75b134e5e7b0949f2828519054a76892508d languageName: node linkType: hard +"globals@npm:^17.3.0": + version: 17.3.0 + resolution: "globals@npm:17.3.0" + checksum: 10/44ba2b7db93eb6a2531dfba09219845e21f2e724a4f400eb59518b180b7d5bcf7f65580530e3d3023d7dc2bdbacf5d265fd87c393f567deb9a2b0472b51c9d5e + languageName: node + linkType: hard + "globalthis@npm:^1.0.1, globalthis@npm:^1.0.3, globalthis@npm:^1.0.4": version: 1.0.4 resolution: "globalthis@npm:1.0.4" @@ -33456,9 +33751,9 @@ __metadata: linkType: hard "hono@npm:^4.11.4": - version: 4.12.7 - resolution: "hono@npm:4.12.7" - checksum: 10/fed37e612730491ba9456f8f68f1b8727a5298cd839fff9641a0b7a95b1e8567a05abb819d32621b40988f166b01140cf7d573c9218dee2741004f48e09564d5 + version: 4.12.5 + resolution: "hono@npm:4.12.5" + checksum: 10/3d03cf2885f7c75325869a178bc94291a17a656002b930dc91456cb177366f6f344c7c90c09707c1fcb4c6e40b1f33fac98f1622628061628cabadcf8cf6d3fd languageName: node linkType: hard @@ -34626,7 +34921,16 @@ __metadata: languageName: node linkType: hard -"is-fullwidth-code-point@npm:^5.0.0, is-fullwidth-code-point@npm:^5.1.0": +"is-fullwidth-code-point@npm:^5.0.0": + version: 5.0.0 + resolution: "is-fullwidth-code-point@npm:5.0.0" + dependencies: + get-east-asian-width: "npm:^1.0.0" + checksum: 10/8dfb2d2831b9e87983c136f5c335cd9d14c1402973e357a8ff057904612ed84b8cba196319fabedf9aefe4639e14fe3afe9d9966d1d006ebeb40fe1fed4babe5 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^5.1.0": version: 5.1.0 resolution: "is-fullwidth-code-point@npm:5.1.0" dependencies: @@ -36773,21 +37077,20 @@ __metadata: linkType: hard "knip@npm:^5.42.0": - version: 5.86.0 - resolution: "knip@npm:5.86.0" + version: 5.85.0 + resolution: "knip@npm:5.85.0" dependencies: "@nodelib/fs.walk": "npm:^1.2.3" fast-glob: "npm:^3.3.3" formatly: "npm:^0.3.0" jiti: "npm:^2.6.0" + js-yaml: "npm:^4.1.1" minimist: "npm:^1.2.8" - oxc-resolver: "npm:^11.19.1" + oxc-resolver: "npm:^11.15.0" picocolors: "npm:^1.1.1" picomatch: "npm:^4.0.1" smol-toml: "npm:^1.5.2" strip-json-comments: "npm:5.0.3" - unbash: "npm:^2.2.0" - yaml: "npm:^2.8.2" zod: "npm:^4.1.11" peerDependencies: "@types/node": ">=18" @@ -36795,7 +37098,7 @@ __metadata: bin: knip: bin/knip.js knip-bun: bin/knip-bun.js - checksum: 10/1b8c94f62d2868b0c62499474f462dc09d57e10e73335c01caacff8e0c0b120f441e0881028db30b6a1c185f98a78e2fa727e8faa150bca40c41848263aee04f + checksum: 10/1b80127b24bad3822c2a128e08c30e33db2c716ccb3c1ee19a082d5f04c7d24f049213e15a6369d9449bf60564a86be16e8f986902ba7251bee17a4530c6c954 languageName: node linkType: hard @@ -37003,18 +37306,18 @@ __metadata: linkType: hard "lint-staged@npm:^16.0.0": - version: 16.3.3 - resolution: "lint-staged@npm:16.3.3" + version: 16.4.0 + resolution: "lint-staged@npm:16.4.0" dependencies: commander: "npm:^14.0.3" listr2: "npm:^9.0.5" - micromatch: "npm:^4.0.8" + picomatch: "npm:^4.0.3" string-argv: "npm:^0.3.2" - tinyexec: "npm:^1.0.2" + tinyexec: "npm:^1.0.4" yaml: "npm:^2.8.2" bin: lint-staged: bin/lint-staged.js - checksum: 10/64b20a0aa8710a89db49b4d4384f44e471de8544133cd9f80b1ebeac148144e43b1553aea2b34bf530fd32b554374ee8128c9332033ba138f1a9685964de1cd3 + checksum: 10/eb7aa0d43e321bbf282ce0c693a3db762aa9b8e5bf29419a49c8877a247cd3a14cf8d519f914f8c8dcd2aea73ac83c0bb44fadb97a30004219e060a780dda74e languageName: node linkType: hard @@ -38825,15 +39128,15 @@ __metadata: languageName: node linkType: hard -"mini-css-extract-plugin@npm:^2.4.2": - version: 2.10.0 - resolution: "mini-css-extract-plugin@npm:2.10.0" +"mini-css-extract-plugin@npm:^2.10.1, mini-css-extract-plugin@npm:^2.4.2": + version: 2.10.1 + resolution: "mini-css-extract-plugin@npm:2.10.1" dependencies: schema-utils: "npm:^4.0.0" tapable: "npm:^2.2.1" peerDependencies: webpack: ^5.0.0 - checksum: 10/bae5350ab82171c6c9a22a4397df14aa69280f5ff0e1ff4d2429ea841bc096927b1e27ba7b75a9c3dd77bd44bab449d6197bd748381f1326cbc8befcb10d1a9e + checksum: 10/2d0cecc3bea85cd7f9b1ce0974f1672976d610a9267e2988ff19f5d03b017bff12b32151a412de0f519a70be7d3b050b499b20101445fb21728cc2d35dd4041a languageName: node linkType: hard @@ -40784,30 +41087,30 @@ __metadata: languageName: node linkType: hard -"oxc-resolver@npm:^11.19.1": - version: 11.19.1 - resolution: "oxc-resolver@npm:11.19.1" +"oxc-resolver@npm:^11.15.0": + version: 11.16.3 + resolution: "oxc-resolver@npm:11.16.3" dependencies: - "@oxc-resolver/binding-android-arm-eabi": "npm:11.19.1" - "@oxc-resolver/binding-android-arm64": "npm:11.19.1" - "@oxc-resolver/binding-darwin-arm64": "npm:11.19.1" - "@oxc-resolver/binding-darwin-x64": "npm:11.19.1" - "@oxc-resolver/binding-freebsd-x64": "npm:11.19.1" - "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.19.1" - "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.19.1" - "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-arm64-musl": "npm:11.19.1" - "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.19.1" - "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-x64-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-x64-musl": "npm:11.19.1" - "@oxc-resolver/binding-openharmony-arm64": "npm:11.19.1" - "@oxc-resolver/binding-wasm32-wasi": "npm:11.19.1" - "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.19.1" - "@oxc-resolver/binding-win32-ia32-msvc": "npm:11.19.1" - "@oxc-resolver/binding-win32-x64-msvc": "npm:11.19.1" + "@oxc-resolver/binding-android-arm-eabi": "npm:11.16.3" + "@oxc-resolver/binding-android-arm64": "npm:11.16.3" + "@oxc-resolver/binding-darwin-arm64": "npm:11.16.3" + "@oxc-resolver/binding-darwin-x64": "npm:11.16.3" + "@oxc-resolver/binding-freebsd-x64": "npm:11.16.3" + "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.16.3" + "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.16.3" + "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.16.3" + "@oxc-resolver/binding-linux-arm64-musl": "npm:11.16.3" + "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.16.3" + "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.16.3" + "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.16.3" + "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.16.3" + "@oxc-resolver/binding-linux-x64-gnu": "npm:11.16.3" + "@oxc-resolver/binding-linux-x64-musl": "npm:11.16.3" + "@oxc-resolver/binding-openharmony-arm64": "npm:11.16.3" + "@oxc-resolver/binding-wasm32-wasi": "npm:11.16.3" + "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.16.3" + "@oxc-resolver/binding-win32-ia32-msvc": "npm:11.16.3" + "@oxc-resolver/binding-win32-x64-msvc": "npm:11.16.3" dependenciesMeta: "@oxc-resolver/binding-android-arm-eabi": optional: true @@ -40849,7 +41152,7 @@ __metadata: optional: true "@oxc-resolver/binding-win32-x64-msvc": optional: true - checksum: 10/a6c8fdb2ef4bf9bb84f28e58685457de427d31f74373c0fbd6d1106010cab33027fa3b4336b1b86d0df0a089cd73a6060b730b1b24974d56c59f6fa29c559f9d + checksum: 10/2d0da140e34a74347d03a233488ad0284bbb252a6d250b7ca78d5a431d04d72b8275d896b8fb0d03846f221bcbcb2395739187d2645bf84d1d1332b74b7720be languageName: node linkType: hard @@ -42463,13 +42766,13 @@ __metadata: linkType: hard "postcss@npm:^8.1.0, postcss@npm:^8.4.33, postcss@npm:^8.5.1, postcss@npm:^8.5.6": - version: 8.5.8 - resolution: "postcss@npm:8.5.8" + version: 8.5.6 + resolution: "postcss@npm:8.5.6" dependencies: nanoid: "npm:^3.3.11" picocolors: "npm:^1.1.1" source-map-js: "npm:^1.2.1" - checksum: 10/cbacbfd7f767e2c820d4bf09a3a744834dd7d14f69ff08d1f57b1a7defce9ae5efcf31981890d9697a972a64e9965de677932ef28e4c8ba23a87aad45b82c459 + checksum: 10/9e4fbe97574091e9736d0e82a591e29aa100a0bf60276a926308f8c57249698935f35c5d2f4e80de778d0cbb8dcffab4f383d85fd50c5649aca421c3df729b86 languageName: node linkType: hard @@ -45194,32 +45497,35 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.27.3, rollup@npm:^4.43.0": - version: 4.53.3 - resolution: "rollup@npm:4.53.3" +"rollup@npm:^4.27.3, rollup@npm:^4.43.0, rollup@npm:^4.59.0": + version: 4.59.0 + resolution: "rollup@npm:4.59.0" dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.53.3" - "@rollup/rollup-android-arm64": "npm:4.53.3" - "@rollup/rollup-darwin-arm64": "npm:4.53.3" - "@rollup/rollup-darwin-x64": "npm:4.53.3" - "@rollup/rollup-freebsd-arm64": "npm:4.53.3" - "@rollup/rollup-freebsd-x64": "npm:4.53.3" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.53.3" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.53.3" - "@rollup/rollup-linux-arm64-gnu": "npm:4.53.3" - "@rollup/rollup-linux-arm64-musl": "npm:4.53.3" - "@rollup/rollup-linux-loong64-gnu": "npm:4.53.3" - "@rollup/rollup-linux-ppc64-gnu": "npm:4.53.3" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.53.3" - "@rollup/rollup-linux-riscv64-musl": "npm:4.53.3" - "@rollup/rollup-linux-s390x-gnu": "npm:4.53.3" - "@rollup/rollup-linux-x64-gnu": "npm:4.53.3" - "@rollup/rollup-linux-x64-musl": "npm:4.53.3" - "@rollup/rollup-openharmony-arm64": "npm:4.53.3" - "@rollup/rollup-win32-arm64-msvc": "npm:4.53.3" - "@rollup/rollup-win32-ia32-msvc": "npm:4.53.3" - "@rollup/rollup-win32-x64-gnu": "npm:4.53.3" - "@rollup/rollup-win32-x64-msvc": "npm:4.53.3" + "@rollup/rollup-android-arm-eabi": "npm:4.59.0" + "@rollup/rollup-android-arm64": "npm:4.59.0" + "@rollup/rollup-darwin-arm64": "npm:4.59.0" + "@rollup/rollup-darwin-x64": "npm:4.59.0" + "@rollup/rollup-freebsd-arm64": "npm:4.59.0" + "@rollup/rollup-freebsd-x64": "npm:4.59.0" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.59.0" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.59.0" + "@rollup/rollup-linux-arm64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-arm64-musl": "npm:4.59.0" + "@rollup/rollup-linux-loong64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-loong64-musl": "npm:4.59.0" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-ppc64-musl": "npm:4.59.0" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-riscv64-musl": "npm:4.59.0" + "@rollup/rollup-linux-s390x-gnu": "npm:4.59.0" + "@rollup/rollup-linux-x64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-x64-musl": "npm:4.59.0" + "@rollup/rollup-openbsd-x64": "npm:4.59.0" + "@rollup/rollup-openharmony-arm64": "npm:4.59.0" + "@rollup/rollup-win32-arm64-msvc": "npm:4.59.0" + "@rollup/rollup-win32-ia32-msvc": "npm:4.59.0" + "@rollup/rollup-win32-x64-gnu": "npm:4.59.0" + "@rollup/rollup-win32-x64-msvc": "npm:4.59.0" "@types/estree": "npm:1.0.8" fsevents: "npm:~2.3.2" dependenciesMeta: @@ -45245,8 +45551,12 @@ __metadata: optional: true "@rollup/rollup-linux-loong64-gnu": optional: true + "@rollup/rollup-linux-loong64-musl": + optional: true "@rollup/rollup-linux-ppc64-gnu": optional: true + "@rollup/rollup-linux-ppc64-musl": + optional: true "@rollup/rollup-linux-riscv64-gnu": optional: true "@rollup/rollup-linux-riscv64-musl": @@ -45257,6 +45567,8 @@ __metadata: optional: true "@rollup/rollup-linux-x64-musl": optional: true + "@rollup/rollup-openbsd-x64": + optional: true "@rollup/rollup-openharmony-arm64": optional: true "@rollup/rollup-win32-arm64-msvc": @@ -45271,7 +45583,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: 10/e2eff82405061fa907f15dfbf742b1f5fb4b214495c00989bcdbe21da5fcb3f6dec3deabacec491300a53c99da409586cfc77bdf29b411fccb9089b72cd3728d + checksum: 10/728237932aad7022c0640cd126b9fe5285f2578099f22a0542229a17785320a6553b74582fa5977877541c1faf27de65ed2750bc89dbb55b525405244a46d9f1 languageName: node linkType: hard @@ -45614,7 +45926,7 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:^4.0.0, schema-utils@npm:^4.2.0, schema-utils@npm:^4.3.0, schema-utils@npm:^4.3.3": +"schema-utils@npm:^4.0.0, schema-utils@npm:^4.2.0, schema-utils@npm:^4.3.0, schema-utils@npm:^4.3.2, schema-utils@npm:^4.3.3": version: 4.3.3 resolution: "schema-utils@npm:4.3.3" dependencies: @@ -47724,15 +48036,15 @@ __metadata: linkType: hard "tar@npm:^7.4.3, tar@npm:^7.5.6": - version: 7.5.11 - resolution: "tar@npm:7.5.11" + version: 7.5.10 + resolution: "tar@npm:7.5.10" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" minizlib: "npm:^3.1.0" yallist: "npm:^5.0.0" - checksum: 10/fb2e77ee858a73936c68e066f4a602d428d6f812e6da0cc1e14a41f99498e4f7fd3535e355fa15157240a5538aa416026cfa6306bb0d1d1c1abf314b1f878e9a + checksum: 10/98ba6421a250b233c36a54f7441647bdfee1ed0b916cd57850259a3602154d996f5b8422f67ef5c8ce77f582ed938054775c2873fc7c901e0c7530ed50febc40 languageName: node linkType: hard @@ -48067,10 +48379,10 @@ __metadata: languageName: node linkType: hard -"tinyexec@npm:^1.0.2": - version: 1.0.2 - resolution: "tinyexec@npm:1.0.2" - checksum: 10/cb709ed4240e873d3816e67f851d445f5676e0ae3a52931a60ff571d93d388da09108c8057b62351766133ee05ff3159dd56c3a0fbd39a5933c6639ce8771405 +"tinyexec@npm:^1.0.4": + version: 1.0.4 + resolution: "tinyexec@npm:1.0.4" + checksum: 10/ccebe4044eef6fa5050929df7862fda70b4fb700f15d94aef8ae6109b9d194dbc3a990125d99944fd25b90fe2115e1927f055b909a604c571a81b647ede5757a languageName: node linkType: hard @@ -49027,13 +49339,6 @@ __metadata: languageName: node linkType: hard -"unbash@npm:^2.2.0": - version: 2.2.0 - resolution: "unbash@npm:2.2.0" - checksum: 10/dc169c6cacff0364c3d46dbe3f08f4c812cee63359f94ebace483b1a382585d5a1bf4007c12ed3c73671a0256d0026efc23e4732583ae76b42d8570fc4680667 - languageName: node - linkType: hard - "unbox-primitive@npm:^1.1.0": version: 1.1.0 resolution: "unbox-primitive@npm:1.1.0" @@ -49091,9 +49396,9 @@ __metadata: linkType: hard "undici@npm:^7.2.3, undici@npm:^7.22.0": - version: 7.24.1 - resolution: "undici@npm:7.24.1" - checksum: 10/0af4ec2fc2ae50b1d0636895793ea2274a89a7cd445690089a1b957c4ac4a0336e48ab9ac48a4e8f5023d4b5eab56368c3f17c75d6b4c81b4281b674d1e60c9f + version: 7.22.0 + resolution: "undici@npm:7.22.0" + checksum: 10/a7a1813ba4b74c0d46cc8dd160386202c05699ffc487c5d882cf40e6d2435c8d6faff3b8f8675d09bd1ef0386e370675c26b59b9a8c8b3f17b9f82a42236a927 languageName: node linkType: hard @@ -50190,7 +50495,7 @@ __metadata: languageName: node linkType: hard -"webpack-dev-server@npm:^5.0.0": +"webpack-dev-server@npm:^5.0.0, webpack-dev-server@npm:^5.2.3": version: 5.2.3 resolution: "webpack-dev-server@npm:5.2.3" dependencies: @@ -50259,7 +50564,7 @@ __metadata: languageName: node linkType: hard -"webpack@npm:^5, webpack@npm:~5.105.0": +"webpack@npm:^5, webpack@npm:^5.105.4, webpack@npm:~5.105.0": version: 5.105.4 resolution: "webpack@npm:5.105.4" dependencies: @@ -50869,12 +51174,12 @@ __metadata: linkType: soft "yauzl@npm:^3.0.0": - version: 3.2.1 - resolution: "yauzl@npm:3.2.1" + version: 3.2.0 + resolution: "yauzl@npm:3.2.0" dependencies: buffer-crc32: "npm:~0.2.3" pend: "npm:~1.2.0" - checksum: 10/15dfae75fbfe59c6a1b7a2cb27a995cda0ee70549d32d6b19937e84897436170f169f6bbefc34b9e9beb9c9114a1b8a8a40e7687a907909a19681ebcbf35a1f3 + checksum: 10/a3cd2bfcf7590673bb35750f2a4e5107e3cc939d32d98a072c0673fe42329e390f471b4a53dbbd72512229099b18aa3b79e6ddb87a73b3a17446080c903a2c4b languageName: node linkType: hard From c95a130f52115d0c3cac875d4a786879b704f36c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 13 Mar 2026 15:40:15 +0100 Subject: [PATCH 12/45] Add runCliModule helper for standalone module execution Add a public `runCliModule` function to `@backstage/cli-node` that allows CLI module packages to be executed directly as standalone programs, without needing to be wired into a larger CLI host. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-node/package.json | 2 + packages/cli-node/report.api.md | 7 + packages/cli-node/src/cli-module/index.ts | 1 + .../cli-node/src/cli-module/runCliModule.ts | 232 ++++++++++++++++++ yarn.lock | 4 +- 5 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 packages/cli-node/src/cli-module/runCliModule.ts diff --git a/packages/cli-node/package.json b/packages/cli-node/package.json index 4fa5af208c..95322ad2f0 100644 --- a/packages/cli-node/package.json +++ b/packages/cli-node/package.json @@ -37,6 +37,8 @@ "@manypkg/get-packages": "^1.1.3", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "^3.0.0", + "chalk": "^4.0.0", + "commander": "^12.0.0", "fs-extra": "^11.2.0", "semver": "^7.5.3", "yaml": "^2.0.0", diff --git a/packages/cli-node/report.api.md b/packages/cli-node/report.api.md index b979fff0b0..2fac82080b 100644 --- a/packages/cli-node/report.api.md +++ b/packages/cli-node/report.api.md @@ -253,6 +253,13 @@ export class PackageRoles { static getRoleInfo(role: string): PackageRoleInfo; } +// @public +export function runCliModule(options: { + module: CliModule; + name: string; + version?: string; +}): Promise; + // @public export function runConcurrentTasks( options: ConcurrentTasksOptions, diff --git a/packages/cli-node/src/cli-module/index.ts b/packages/cli-node/src/cli-module/index.ts index 646073a815..56324c3423 100644 --- a/packages/cli-node/src/cli-module/index.ts +++ b/packages/cli-node/src/cli-module/index.ts @@ -15,4 +15,5 @@ */ export { createCliModule } from './createCliModule'; +export { runCliModule } from './runCliModule'; export type { CliCommand, CliCommandContext, CliModule } from './types'; diff --git a/packages/cli-node/src/cli-module/runCliModule.ts b/packages/cli-node/src/cli-module/runCliModule.ts new file mode 100644 index 0000000000..84893f0cac --- /dev/null +++ b/packages/cli-node/src/cli-module/runCliModule.ts @@ -0,0 +1,232 @@ +/* + * 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 { + OpaqueCliModule, + OpaqueCommandTreeNode, + OpaqueCommandLeafNode, +} from '@internal/cli'; +import type { CommandNode } from '@internal/cli'; +import { Command } from 'commander'; +import chalk from 'chalk'; +import { isError, stringifyError } from '@backstage/errors'; +import type { CliModule, CliCommand } from './types'; + +function isCommandHidden(node: CommandNode): boolean { + if (OpaqueCommandLeafNode.isType(node)) { + const { command } = OpaqueCommandLeafNode.toInternal(node); + return !!command.deprecated || !!command.experimental; + } + const { children } = OpaqueCommandTreeNode.toInternal(node); + return children.every(child => isCommandHidden(child)); +} + +function buildCommandGraph(commands: ReadonlyArray): CommandNode[] { + const graph: CommandNode[] = []; + + for (const command of commands) { + const { path } = command; + let current = graph; + + for (let i = 0; i < path.length - 1; i++) { + const name = path[i]; + let next = current.find( + n => + OpaqueCommandTreeNode.isType(n) && + OpaqueCommandTreeNode.toInternal(n).name === name, + ); + if (!next) { + next = OpaqueCommandTreeNode.createInstance('v1', { + name, + children: [], + }); + current.push(next); + } + current = OpaqueCommandTreeNode.toInternal(next).children; + } + + current.push( + OpaqueCommandLeafNode.createInstance('v1', { + name: path[path.length - 1], + command, + }), + ); + } + + return graph; +} + +function exitWithError(error: unknown): never { + if (!isError(error)) { + process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`); + process.exit(1); + } + process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`); + process.exit( + 'code' in error && typeof error.code === 'number' ? error.code : 1, + ); +} + +function registerCommands( + graph: CommandNode[], + program: Command, + programName: string, +): void { + const queue = graph.map(node => ({ node, argParser: program })); + + while (queue.length) { + const { node, argParser } = queue.shift()!; + + if (OpaqueCommandTreeNode.isType(node)) { + const internal = OpaqueCommandTreeNode.toInternal(node); + const treeParser = argParser + .command(`${internal.name} [command]`, { + hidden: isCommandHidden(node), + }) + .description(internal.name); + + queue.push( + ...internal.children.map(child => ({ + node: child, + argParser: treeParser, + })), + ); + } else { + const internal = OpaqueCommandLeafNode.toInternal(node); + argParser + .command(internal.name, { + hidden: + !!internal.command.deprecated || !!internal.command.experimental, + }) + .description(internal.command.description) + .helpOption(false) + .allowUnknownOption(true) + .allowExcessArguments(true) + .action(async () => { + try { + const args = program.parseOptions(process.argv); + + const nonProcessArgs = args.operands.slice(2); + const positionalArgs = []; + let index = 0; + for ( + let argIndex = 0; + argIndex < nonProcessArgs.length; + argIndex++ + ) { + if ( + argIndex === index && + internal.command.path[argIndex] === nonProcessArgs[argIndex] + ) { + index += 1; + continue; + } + positionalArgs.push(nonProcessArgs[argIndex]); + } + const context = { + args: [...positionalArgs, ...args.unknown], + info: { + usage: [programName, ...internal.command.path].join(' '), + name: internal.command.path.join(' '), + }, + }; + + if (typeof internal.command.execute === 'function') { + await internal.command.execute(context); + } else { + const mod = await internal.command.execute.loader(); + const fn = + typeof mod.default === 'function' + ? mod.default + : (mod.default as any).default; + await fn(context); + } + process.exit(0); + } catch (error: unknown) { + exitWithError(error); + } + }); + } + } +} + +/** + * Runs a CLI module as a standalone program. + * + * This helper extracts the commands from a {@link CliModule} and exposes + * them as a fully functional CLI with help output and argument parsing. + * It is intended to be called from a module package's `bin` entry point + * so that the module can be executed directly without being wired into + * a larger CLI host. + * + * @example + * ```ts + * #!/usr/bin/env node + * import { runCliModule } from '@backstage/cli-node'; + * import cliModule from './index'; + * + * runCliModule({ + * module: cliModule, + * name: 'backstage-auth', + * version: require('../package.json').version, + * }); + * ``` + * + * @public + */ +export async function runCliModule(options: { + /** The CLI module to run. */ + module: CliModule; + /** The program name shown in help output and usage strings. */ + name: string; + /** The version string shown when `--version` is passed. */ + version?: string; +}): Promise { + const { module: cliModule, name, version } = options; + + if (!OpaqueCliModule.isType(cliModule)) { + throw new Error( + `Invalid CLI module: expected a module created with createCliModule`, + ); + } + + const internal = OpaqueCliModule.toInternal(cliModule); + const commands = await internal.commands; + const graph = buildCommandGraph(commands); + + const program = new Command(); + program.name(name).allowUnknownOption(true).allowExcessArguments(true); + + if (version) { + program.version(version); + } + + registerCommands(graph, program, name); + + program.on('command:*', () => { + console.log(); + console.log(chalk.red(`Invalid command: ${program.args.join(' ')}`)); + console.log(); + program.outputHelp(); + process.exit(1); + }); + + process.on('unhandledRejection', rejection => { + exitWithError(rejection); + }); + + await program.parseAsync(process.argv); +} diff --git a/yarn.lock b/yarn.lock index 98d39db148..d753c5d9cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3030,6 +3030,8 @@ __metadata: "@types/yarnpkg__lockfile": "npm:^1.1.4" "@yarnpkg/lockfile": "npm:^1.1.0" "@yarnpkg/parsers": "npm:^3.0.0" + chalk: "npm:^4.0.0" + commander: "npm:^12.0.0" fs-extra: "npm:^11.2.0" semver: "npm:^7.5.3" yaml: "npm:^2.0.0" @@ -27535,7 +27537,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^12.1.0": +"commander@npm:^12.0.0, commander@npm:^12.1.0": version: 12.1.0 resolution: "commander@npm:12.1.0" checksum: 10/cdaeb672d979816853a4eed7f1310a9319e8b976172485c2a6b437ed0db0a389a44cfb222bfbde772781efa9f215bdd1b936f80d6b249485b465c6cb906e1f93 From 401c1f7e24bdb9de33bbcfdbd5f2a38777f967d2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 11:25:57 +0100 Subject: [PATCH 13/45] Resolve CLI version dynamically in info module The info command now tries to resolve the @backstage/cli version at runtime instead of using a hardcoded relative path. This allows the module to work standalone when the CLI package is not present. The module's own version is always reported as infoModuleVersion. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-info/src/commands/info.ts | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/cli-module-info/src/commands/info.ts b/packages/cli-module-info/src/commands/info.ts index dd9f892d27..e7307e18c2 100644 --- a/packages/cli-module-info/src/commands/info.ts +++ b/packages/cli-module-info/src/commands/info.ts @@ -15,9 +15,7 @@ */ import { cli } from 'cleye'; -const { version: cliVersion } = require('../../../package.json') as { - version: string; -}; +import { version as infoModuleVersion } from '../../package.json'; import os from 'node:os'; import { runOutput, targetPaths, findOwnPaths } from '@backstage/cli-common'; import { @@ -101,12 +99,27 @@ export default async ({ args, info }: CliCommandContext) => { } } - // Build system info + // Try to resolve the CLI package version — it may not be installed + // when this module is executed standalone. + let cliVersion: string | undefined; + try { + cliVersion = ( + require(require.resolve('@backstage/cli/package.json', { + paths: [process.cwd()], + })) as { version: string } + ).version; + } catch { + /* not available */ + } + const systemInfo = { os: `${os.type} ${os.release} - ${os.platform}/${os.arch}`, node: process.version, yarn: yarnVersion, - cli: { version: cliVersion, local: isLocal }, + ...(cliVersion + ? { cli: { version: cliVersion, local: isLocal } } + : undefined), + infoModuleVersion, backstage: backstageVersion, }; @@ -210,8 +223,11 @@ export default async ({ args, info }: CliCommandContext) => { console.log(`OS: ${systemInfo.os}`); console.log(`node: ${systemInfo.node}`); console.log(`yarn: ${systemInfo.yarn}`); - console.log(`cli: ${cliVersion} (${isLocal ? 'local' : 'installed'})`); - console.log(`backstage: ${backstageVersion}`); + if (cliVersion) { + console.log(`cli: ${cliVersion} (${isLocal ? 'local' : 'installed'})`); + } + console.log(`info module: ${infoModuleVersion}`); + console.log(`backstage: ${backstageVersion}`); console.log(); // Print installed dependencies From 64a96d9d9f6363e4627e24e6df21f79d024f5a1b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 11:47:47 +0100 Subject: [PATCH 14/45] Add bin entry points for standalone CLI module execution Each CLI module package now includes a bin script and cli.ts entry point, allowing modules to be executed directly via npx without being wired into the main @backstage/cli package. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-auth/bin/cli-module-auth | 33 +++++++++++++++++++ packages/cli-module-auth/package.json | 6 ++-- packages/cli-module-auth/src/cli.ts | 26 +++++++++++++++ .../cli-module-build/bin/cli-module-build | 33 +++++++++++++++++++ packages/cli-module-build/package.json | 6 ++-- packages/cli-module-build/src/cli.ts | 26 +++++++++++++++ .../cli-module-config/bin/cli-module-config | 33 +++++++++++++++++++ packages/cli-module-config/package.json | 6 ++-- packages/cli-module-config/src/cli.ts | 26 +++++++++++++++ .../bin/cli-module-create-github-app | 33 +++++++++++++++++++ .../cli-module-create-github-app/package.json | 6 ++-- .../cli-module-create-github-app/src/cli.ts | 26 +++++++++++++++ packages/cli-module-info/bin/cli-module-info | 33 +++++++++++++++++++ packages/cli-module-info/package.json | 6 ++-- packages/cli-module-info/src/cli.ts | 26 +++++++++++++++ packages/cli-module-lint/bin/cli-module-lint | 33 +++++++++++++++++++ packages/cli-module-lint/package.json | 6 ++-- packages/cli-module-lint/src/cli.ts | 26 +++++++++++++++ .../bin/cli-module-maintenance | 33 +++++++++++++++++++ packages/cli-module-maintenance/package.json | 6 ++-- packages/cli-module-maintenance/src/cli.ts | 26 +++++++++++++++ .../cli-module-migrate/bin/cli-module-migrate | 33 +++++++++++++++++++ packages/cli-module-migrate/package.json | 6 ++-- packages/cli-module-migrate/src/cli.ts | 26 +++++++++++++++ packages/cli-module-new/bin/cli-module-new | 33 +++++++++++++++++++ packages/cli-module-new/package.json | 6 ++-- packages/cli-module-new/src/cli.ts | 26 +++++++++++++++ .../bin/cli-module-test-jest | 33 +++++++++++++++++++ packages/cli-module-test-jest/package.json | 6 ++-- packages/cli-module-test-jest/src/cli.ts | 26 +++++++++++++++ .../bin/cli-module-translations | 33 +++++++++++++++++++ packages/cli-module-translations/package.json | 6 ++-- packages/cli-module-translations/src/cli.ts | 26 +++++++++++++++ yarn.lock | 22 +++++++++++++ 34 files changed, 715 insertions(+), 22 deletions(-) create mode 100755 packages/cli-module-auth/bin/cli-module-auth create mode 100644 packages/cli-module-auth/src/cli.ts create mode 100755 packages/cli-module-build/bin/cli-module-build create mode 100644 packages/cli-module-build/src/cli.ts create mode 100755 packages/cli-module-config/bin/cli-module-config create mode 100644 packages/cli-module-config/src/cli.ts create mode 100755 packages/cli-module-create-github-app/bin/cli-module-create-github-app create mode 100644 packages/cli-module-create-github-app/src/cli.ts create mode 100755 packages/cli-module-info/bin/cli-module-info create mode 100644 packages/cli-module-info/src/cli.ts create mode 100755 packages/cli-module-lint/bin/cli-module-lint create mode 100644 packages/cli-module-lint/src/cli.ts create mode 100755 packages/cli-module-maintenance/bin/cli-module-maintenance create mode 100644 packages/cli-module-maintenance/src/cli.ts create mode 100755 packages/cli-module-migrate/bin/cli-module-migrate create mode 100644 packages/cli-module-migrate/src/cli.ts create mode 100755 packages/cli-module-new/bin/cli-module-new create mode 100644 packages/cli-module-new/src/cli.ts create mode 100755 packages/cli-module-test-jest/bin/cli-module-test-jest create mode 100644 packages/cli-module-test-jest/src/cli.ts create mode 100755 packages/cli-module-translations/bin/cli-module-translations create mode 100644 packages/cli-module-translations/src/cli.ts diff --git a/packages/cli-module-auth/bin/cli-module-auth b/packages/cli-module-auth/bin/cli-module-auth new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-auth/bin/cli-module-auth @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-auth/package.json b/packages/cli-module-auth/package.json index d00b1010f6..c3f4b55d0e 100644 --- a/packages/cli-module-auth/package.json +++ b/packages/cli-module-auth/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -47,5 +48,6 @@ "@types/fs-extra": "^11.0.0", "@types/proper-lockfile": "^4", "cross-fetch": "^4.0.0" - } + }, + "bin": "bin/cli-module-auth" } diff --git a/packages/cli-module-auth/src/cli.ts b/packages/cli-module-auth/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-auth/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-build/bin/cli-module-build b/packages/cli-module-build/bin/cli-module-build new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-build/bin/cli-module-build @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index 0a4849671c..dd59b6948f 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -88,5 +89,6 @@ "cross-spawn": "^7.0.6", "rollup": "^4.59.0", "ts-morph": "^24.0.0" - } + }, + "bin": "bin/cli-module-build" } diff --git a/packages/cli-module-build/src/cli.ts b/packages/cli-module-build/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-build/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-config/bin/cli-module-config b/packages/cli-module-config/bin/cli-module-config new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-config/bin/cli-module-config @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-config/package.json b/packages/cli-module-config/package.json index 841f40de35..bcf5059280 100644 --- a/packages/cli-module-config/package.json +++ b/packages/cli-module-config/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -46,5 +47,6 @@ }, "devDependencies": { "@backstage/cli": "workspace:^" - } + }, + "bin": "bin/cli-module-config" } diff --git a/packages/cli-module-config/src/cli.ts b/packages/cli-module-config/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-config/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-create-github-app/bin/cli-module-create-github-app b/packages/cli-module-create-github-app/bin/cli-module-create-github-app new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-create-github-app/bin/cli-module-create-github-app @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-create-github-app/package.json b/packages/cli-module-create-github-app/package.json index 878ac0b3f8..81daa72058 100644 --- a/packages/cli-module-create-github-app/package.json +++ b/packages/cli-module-create-github-app/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -46,5 +47,6 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/fs-extra": "^11.0.0" - } + }, + "bin": "bin/cli-module-create-github-app" } diff --git a/packages/cli-module-create-github-app/src/cli.ts b/packages/cli-module-create-github-app/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-create-github-app/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-info/bin/cli-module-info b/packages/cli-module-info/bin/cli-module-info new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-info/bin/cli-module-info @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-info/package.json b/packages/cli-module-info/package.json index 5e1dd894e9..50f79da6f0 100644 --- a/packages/cli-module-info/package.json +++ b/packages/cli-module-info/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -40,5 +41,6 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/fs-extra": "^11.0.0" - } + }, + "bin": "bin/cli-module-info" } diff --git a/packages/cli-module-info/src/cli.ts b/packages/cli-module-info/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-info/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-lint/bin/cli-module-lint b/packages/cli-module-lint/bin/cli-module-lint new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-lint/bin/cli-module-lint @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-lint/package.json b/packages/cli-module-lint/package.json index 40839a0046..50edbae5eb 100644 --- a/packages/cli-module-lint/package.json +++ b/packages/cli-module-lint/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -44,5 +45,6 @@ "@backstage/cli": "workspace:^", "@types/fs-extra": "^11.0.0", "@types/shell-quote": "^1.7.5" - } + }, + "bin": "bin/cli-module-lint" } diff --git a/packages/cli-module-lint/src/cli.ts b/packages/cli-module-lint/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-lint/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-maintenance/bin/cli-module-maintenance b/packages/cli-module-maintenance/bin/cli-module-maintenance new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-maintenance/bin/cli-module-maintenance @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-maintenance/package.json b/packages/cli-module-maintenance/package.json index 5d321f88f0..69888e502f 100644 --- a/packages/cli-module-maintenance/package.json +++ b/packages/cli-module-maintenance/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -41,5 +42,6 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/fs-extra": "^11.0.0" - } + }, + "bin": "bin/cli-module-maintenance" } diff --git a/packages/cli-module-maintenance/src/cli.ts b/packages/cli-module-maintenance/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-maintenance/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-migrate/bin/cli-module-migrate b/packages/cli-module-migrate/bin/cli-module-migrate new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-migrate/bin/cli-module-migrate @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-migrate/package.json b/packages/cli-module-migrate/package.json index 660b85dff2..49faa42261 100644 --- a/packages/cli-module-migrate/package.json +++ b/packages/cli-module-migrate/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -44,5 +45,6 @@ "@backstage/test-utils": "workspace:^", "@types/fs-extra": "^11.0.0", "msw": "^1.0.0" - } + }, + "bin": "bin/cli-module-migrate" } diff --git a/packages/cli-module-migrate/src/cli.ts b/packages/cli-module-migrate/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-migrate/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-new/bin/cli-module-new b/packages/cli-module-new/bin/cli-module-new new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-new/bin/cli-module-new @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-new/package.json b/packages/cli-module-new/package.json index 5a04becd22..a49ccaa6d7 100644 --- a/packages/cli-module-new/package.json +++ b/packages/cli-module-new/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -35,5 +36,6 @@ }, "devDependencies": { "@backstage/cli": "workspace:^" - } + }, + "bin": "bin/cli-module-new" } diff --git a/packages/cli-module-new/src/cli.ts b/packages/cli-module-new/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-new/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-test-jest/bin/cli-module-test-jest b/packages/cli-module-test-jest/bin/cli-module-test-jest new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-test-jest/bin/cli-module-test-jest @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-test-jest/package.json b/packages/cli-module-test-jest/package.json index 7df933dee9..5fef26bbab 100644 --- a/packages/cli-module-test-jest/package.json +++ b/packages/cli-module-test-jest/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -35,5 +36,6 @@ }, "devDependencies": { "@backstage/cli": "workspace:^" - } + }, + "bin": "bin/cli-module-test-jest" } diff --git a/packages/cli-module-test-jest/src/cli.ts b/packages/cli-module-test-jest/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-test-jest/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/packages/cli-module-translations/bin/cli-module-translations b/packages/cli-module-translations/bin/cli-module-translations new file mode 100755 index 0000000000..533974f6a9 --- /dev/null +++ b/packages/cli-module-translations/bin/cli-module-translations @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const path = require('node:path'); + +/* eslint-disable-next-line no-restricted-syntax */ +const isLocal = require('node:fs').existsSync( + path.resolve(__dirname, '../src'), +); + +if (!isLocal) { + const { runCliModule } = require('@backstage/cli-node'); + const cliModule = require('..').default; + const pkg = require('../package.json'); + runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); +} else { + require('@backstage/cli/config/nodeTransform.cjs'); + require('../src/cli'); +} diff --git a/packages/cli-module-translations/package.json b/packages/cli-module-translations/package.json index 8818ff32d4..f9e642afe7 100644 --- a/packages/cli-module-translations/package.json +++ b/packages/cli-module-translations/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "bin" ], "scripts": { "build": "backstage-cli package build", @@ -35,5 +36,6 @@ }, "devDependencies": { "@backstage/cli": "workspace:^" - } + }, + "bin": "bin/cli-module-translations" } diff --git a/packages/cli-module-translations/src/cli.ts b/packages/cli-module-translations/src/cli.ts new file mode 100644 index 0000000000..6d4b925cf1 --- /dev/null +++ b/packages/cli-module-translations/src/cli.ts @@ -0,0 +1,26 @@ +/* + * 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 { runCliModule } from '@backstage/cli-node'; +import cliModule from './index'; + +const pkg = require('../package.json') as { name: string; version: string }; + +runCliModule({ + module: cliModule, + name: pkg.name, + version: pkg.version, +}); diff --git a/yarn.lock b/yarn.lock index d753c5d9cb..d0f471e49a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2819,6 +2819,8 @@ __metadata: proper-lockfile: "npm:^4.1.2" yaml: "npm:^2.0.0" zod: "npm:^3.25.76" + bin: + cli-module-auth: bin/cli-module-auth languageName: unknown linkType: soft @@ -2881,6 +2883,8 @@ __metadata: webpack: "npm:^5.105.4" webpack-dev-server: "npm:^5.2.3" yn: "npm:^4.0.0" + bin: + cli-module-build: bin/cli-module-build languageName: unknown linkType: soft @@ -2901,6 +2905,8 @@ __metadata: json-schema: "npm:^0.4.0" react-dev-utils: "npm:^12.0.0-next.60" yaml: "npm:^2.0.0" + bin: + cli-module-config: bin/cli-module-config languageName: unknown linkType: soft @@ -2921,6 +2927,8 @@ __metadata: inquirer: "npm:^8.2.0" react-dev-utils: "npm:^12.0.0-next.60" yaml: "npm:^2.0.0" + bin: + cli-module-create-github-app: bin/cli-module-create-github-app languageName: unknown linkType: soft @@ -2935,6 +2943,8 @@ __metadata: cleye: "npm:^2.3.0" fs-extra: "npm:^11.2.0" minimatch: "npm:^10.2.1" + bin: + cli-module-info: bin/cli-module-info languageName: unknown linkType: soft @@ -2953,6 +2963,8 @@ __metadata: fs-extra: "npm:^11.2.0" globby: "npm:^11.0.0" shell-quote: "npm:^1.8.1" + bin: + cli-module-lint: bin/cli-module-lint languageName: unknown linkType: soft @@ -2968,6 +2980,8 @@ __metadata: cleye: "npm:^2.3.0" eslint: "npm:^8.6.0" fs-extra: "npm:^11.2.0" + bin: + cli-module-maintenance: bin/cli-module-maintenance languageName: unknown linkType: soft @@ -2986,6 +3000,8 @@ __metadata: cleye: "npm:^2.3.0" fs-extra: "npm:^11.2.0" msw: "npm:^1.0.0" + bin: + cli-module-migrate: bin/cli-module-migrate languageName: unknown linkType: soft @@ -2995,6 +3011,8 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@backstage/cli-node": "workspace:^" + bin: + cli-module-new: bin/cli-module-new languageName: unknown linkType: soft @@ -3004,6 +3022,8 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@backstage/cli-node": "workspace:^" + bin: + cli-module-test-jest: bin/cli-module-test-jest languageName: unknown linkType: soft @@ -3013,6 +3033,8 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@backstage/cli-node": "workspace:^" + bin: + cli-module-translations: bin/cli-module-translations languageName: unknown linkType: soft From d806b0cc9fdd7989eceb223fd1f4710f5702b099 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 12:34:24 +0100 Subject: [PATCH 15/45] Add automatic discovery of CLI modules from project dependencies The CLI now scans the project root's dependencies and devDependencies for packages with the cli-module role, loading them automatically. Falls back to the built-in set with a deprecation warning when no modules are found. Updated create-app templates and the monorepo root to include all CLI modules as explicit devDependencies. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/cli-discover-modules.md | 31 +++++++++ .changeset/create-app-cli-modules.md | 5 ++ package.json | 11 ++++ packages/cli/src/index.ts | 46 +++++++++---- packages/cli/src/wiring/discoverCliModules.ts | 65 +++++++++++++++++++ .../templates/default-app/package.json.hbs | 11 ++++ .../templates/next-app/package.json.hbs | 11 ++++ yarn.lock | 33 ++++++---- 8 files changed, 191 insertions(+), 22 deletions(-) create mode 100644 .changeset/cli-discover-modules.md create mode 100644 .changeset/create-app-cli-modules.md create mode 100644 packages/cli/src/wiring/discoverCliModules.ts diff --git a/.changeset/cli-discover-modules.md b/.changeset/cli-discover-modules.md new file mode 100644 index 0000000000..428a6eb883 --- /dev/null +++ b/.changeset/cli-discover-modules.md @@ -0,0 +1,31 @@ +--- +'@backstage/cli': minor +--- + +The CLI now automatically discovers CLI modules from the project root's `dependencies` and `devDependencies`. Any installed package with the `cli-module` Backstage role will be loaded automatically without needing to be hardcoded in the CLI itself. + +If no CLI modules are found in the project dependencies, the CLI falls back to the built-in set of modules and prints a deprecation warning. This fallback will be removed in a future release. To prepare for this, add the following CLI modules as `devDependencies` in your root `package.json`: + +```json +{ + "devDependencies": { + "@backstage/cli-module-auth": "backstage:^", + "@backstage/cli-module-build": "backstage:^", + "@backstage/cli-module-config": "backstage:^", + "@backstage/cli-module-create-github-app": "backstage:^", + "@backstage/cli-module-info": "backstage:^", + "@backstage/cli-module-lint": "backstage:^", + "@backstage/cli-module-maintenance": "backstage:^", + "@backstage/cli-module-migrate": "backstage:^", + "@backstage/cli-module-new": "backstage:^", + "@backstage/cli-module-test-jest": "backstage:^", + "@backstage/cli-module-translations": "backstage:^" + } +} +``` + +If you are not using the Backstage Yarn plugin, run the following instead: + +```sh +yarn workspace root add --dev @backstage/cli-module-auth @backstage/cli-module-build @backstage/cli-module-config @backstage/cli-module-create-github-app @backstage/cli-module-info @backstage/cli-module-lint @backstage/cli-module-maintenance @backstage/cli-module-migrate @backstage/cli-module-new @backstage/cli-module-test-jest @backstage/cli-module-translations +``` diff --git a/.changeset/create-app-cli-modules.md b/.changeset/create-app-cli-modules.md new file mode 100644 index 0000000000..4e01b65260 --- /dev/null +++ b/.changeset/create-app-cli-modules.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +The create-app templates now include all standard `@backstage/cli-module-*` packages as `devDependencies`, enabling the CLI's automatic module discovery for newly created projects. diff --git a/package.json b/package.json index d94bdadcbd..962fe132d4 100644 --- a/package.json +++ b/package.json @@ -125,6 +125,17 @@ }, "devDependencies": { "@backstage/cli": "workspace:*", + "@backstage/cli-module-auth": "workspace:*", + "@backstage/cli-module-build": "workspace:*", + "@backstage/cli-module-config": "workspace:*", + "@backstage/cli-module-create-github-app": "workspace:*", + "@backstage/cli-module-info": "workspace:*", + "@backstage/cli-module-lint": "workspace:*", + "@backstage/cli-module-maintenance": "workspace:*", + "@backstage/cli-module-migrate": "workspace:*", + "@backstage/cli-module-new": "workspace:*", + "@backstage/cli-module-test-jest": "workspace:*", + "@backstage/cli-module-translations": "workspace:*", "@backstage/codemods": "workspace:*", "@backstage/create-app": "workspace:*", "@backstage/e2e-test-utils": "workspace:*", diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 8773c3b112..489287c3f2 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -14,20 +14,44 @@ * limitations under the License. */ +import chalk from 'chalk'; import { CliInitializer } from './wiring/CliInitializer'; +import { discoverCliModules } from './wiring/discoverCliModules'; (async () => { const initializer = new CliInitializer(); - initializer.add(import('@backstage/cli-module-build')); - initializer.add(import('@backstage/cli-module-config')); - initializer.add(import('@backstage/cli-module-create-github-app')); - initializer.add(import('@backstage/cli-module-info')); - initializer.add(import('@backstage/cli-module-lint')); - initializer.add(import('@backstage/cli-module-maintenance')); - initializer.add(import('@backstage/cli-module-migrate')); - initializer.add(import('@backstage/cli-module-new')); - initializer.add(import('@backstage/cli-module-test-jest')); - initializer.add(import('@backstage/cli-module-translations')); - initializer.add(import('@backstage/cli-module-auth')); + + const discoveredModules = discoverCliModules(); + + if (discoveredModules.length > 0) { + for (const moduleName of discoveredModules) { + initializer.add(import(moduleName)); + } + } else { + // No CLI modules found in the project root; fall back to the built-in + // set while printing a deprecation warning. + console.error( + chalk.yellow( + `No CLI modules found in the project root dependencies. ` + + `Falling back to the built-in set of modules.\n` + + `This fallback will be removed in a future release. ` + + `Please add the CLI modules you need as devDependencies ` + + `in your root package.json.\n`, + ), + ); + + initializer.add(import('@backstage/cli-module-build')); + initializer.add(import('@backstage/cli-module-config')); + initializer.add(import('@backstage/cli-module-create-github-app')); + initializer.add(import('@backstage/cli-module-info')); + initializer.add(import('@backstage/cli-module-lint')); + initializer.add(import('@backstage/cli-module-maintenance')); + initializer.add(import('@backstage/cli-module-migrate')); + initializer.add(import('@backstage/cli-module-new')); + initializer.add(import('@backstage/cli-module-test-jest')); + initializer.add(import('@backstage/cli-module-translations')); + initializer.add(import('@backstage/cli-module-auth')); + } + await initializer.run(); })(); diff --git a/packages/cli/src/wiring/discoverCliModules.ts b/packages/cli/src/wiring/discoverCliModules.ts new file mode 100644 index 0000000000..dac80c1344 --- /dev/null +++ b/packages/cli/src/wiring/discoverCliModules.ts @@ -0,0 +1,65 @@ +/* + * 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 { targetPaths } from '@backstage/cli-common'; +import { PackageRoles } from '@backstage/cli-node'; +import fs from 'node:fs'; +import { resolve as resolvePath } from 'node:path'; + +/** + * Scans the target project root's package.json for dependencies that are CLI + * modules (packages with `backstage.role === 'cli-module'`). + * + * Returns the names of discovered CLI module packages, or an empty array if + * none are found or the project root cannot be read. + */ +export function discoverCliModules(): string[] { + const rootDir = targetPaths.rootDir; + const pkgJsonPath = resolvePath(rootDir, 'package.json'); + + let projectPkg: { + dependencies?: Record; + devDependencies?: Record; + }; + try { + projectPkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8')); + } catch { + return []; + } + + const allDeps = { + ...projectPkg.dependencies, + ...projectPkg.devDependencies, + }; + + const modules: string[] = []; + + for (const depName of Object.keys(allDeps)) { + try { + const depPkgPath = require.resolve(`${depName}/package.json`, { + paths: [rootDir], + }); + const depPkg = JSON.parse(fs.readFileSync(depPkgPath, 'utf8')); + if (PackageRoles.getRoleFromPackage(depPkg) === 'cli-module') { + modules.push(depName); + } + } catch { + // Skip packages that can't be resolved or read + } + } + + return modules; +} diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index 229ed5ffa0..ca29f02dc0 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -28,6 +28,17 @@ ], "devDependencies": { "@backstage/cli": "^{{version '@backstage/cli'}}", + "@backstage/cli-module-auth": "^{{version '@backstage/cli-module-auth'}}", + "@backstage/cli-module-build": "^{{version '@backstage/cli-module-build'}}", + "@backstage/cli-module-config": "^{{version '@backstage/cli-module-config'}}", + "@backstage/cli-module-create-github-app": "^{{version '@backstage/cli-module-create-github-app'}}", + "@backstage/cli-module-info": "^{{version '@backstage/cli-module-info'}}", + "@backstage/cli-module-lint": "^{{version '@backstage/cli-module-lint'}}", + "@backstage/cli-module-maintenance": "^{{version '@backstage/cli-module-maintenance'}}", + "@backstage/cli-module-migrate": "^{{version '@backstage/cli-module-migrate'}}", + "@backstage/cli-module-new": "^{{version '@backstage/cli-module-new'}}", + "@backstage/cli-module-test-jest": "^{{version '@backstage/cli-module-test-jest'}}", + "@backstage/cli-module-translations": "^{{version '@backstage/cli-module-translations'}}", "@backstage/e2e-test-utils": "^{{version '@backstage/e2e-test-utils'}}", "@jest/environment-jsdom-abstract": "^30.0.0", "@playwright/test": "^1.32.3", diff --git a/packages/create-app/templates/next-app/package.json.hbs b/packages/create-app/templates/next-app/package.json.hbs index 27d5880c11..110ebc160c 100644 --- a/packages/create-app/templates/next-app/package.json.hbs +++ b/packages/create-app/templates/next-app/package.json.hbs @@ -50,6 +50,17 @@ ], "devDependencies": { "@backstage/cli": "^{{version '@backstage/cli'}}", + "@backstage/cli-module-auth": "^{{version '@backstage/cli-module-auth'}}", + "@backstage/cli-module-build": "^{{version '@backstage/cli-module-build'}}", + "@backstage/cli-module-config": "^{{version '@backstage/cli-module-config'}}", + "@backstage/cli-module-create-github-app": "^{{version '@backstage/cli-module-create-github-app'}}", + "@backstage/cli-module-info": "^{{version '@backstage/cli-module-info'}}", + "@backstage/cli-module-lint": "^{{version '@backstage/cli-module-lint'}}", + "@backstage/cli-module-maintenance": "^{{version '@backstage/cli-module-maintenance'}}", + "@backstage/cli-module-migrate": "^{{version '@backstage/cli-module-migrate'}}", + "@backstage/cli-module-new": "^{{version '@backstage/cli-module-new'}}", + "@backstage/cli-module-test-jest": "^{{version '@backstage/cli-module-test-jest'}}", + "@backstage/cli-module-translations": "^{{version '@backstage/cli-module-translations'}}", "@backstage/e2e-test-utils": "^{{version '@backstage/e2e-test-utils'}}", "@jest/environment-jsdom-abstract": "^30.0.0", "@playwright/test": "^1.32.3", diff --git a/yarn.lock b/yarn.lock index d0f471e49a..a5abf933a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2801,7 +2801,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-auth@workspace:^, @backstage/cli-module-auth@workspace:packages/cli-module-auth": +"@backstage/cli-module-auth@workspace:*, @backstage/cli-module-auth@workspace:^, @backstage/cli-module-auth@workspace:packages/cli-module-auth": version: 0.0.0-use.local resolution: "@backstage/cli-module-auth@workspace:packages/cli-module-auth" dependencies: @@ -2824,7 +2824,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-build@workspace:^, @backstage/cli-module-build@workspace:packages/cli-module-build": +"@backstage/cli-module-build@workspace:*, @backstage/cli-module-build@workspace:^, @backstage/cli-module-build@workspace:packages/cli-module-build": version: 0.0.0-use.local resolution: "@backstage/cli-module-build@workspace:packages/cli-module-build" dependencies: @@ -2888,7 +2888,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-config@workspace:^, @backstage/cli-module-config@workspace:packages/cli-module-config": +"@backstage/cli-module-config@workspace:*, @backstage/cli-module-config@workspace:^, @backstage/cli-module-config@workspace:packages/cli-module-config": version: 0.0.0-use.local resolution: "@backstage/cli-module-config@workspace:packages/cli-module-config" dependencies: @@ -2910,7 +2910,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-create-github-app@workspace:^, @backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app": +"@backstage/cli-module-create-github-app@workspace:*, @backstage/cli-module-create-github-app@workspace:^, @backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app": version: 0.0.0-use.local resolution: "@backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app" dependencies: @@ -2932,7 +2932,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-info@workspace:^, @backstage/cli-module-info@workspace:packages/cli-module-info": +"@backstage/cli-module-info@workspace:*, @backstage/cli-module-info@workspace:^, @backstage/cli-module-info@workspace:packages/cli-module-info": version: 0.0.0-use.local resolution: "@backstage/cli-module-info@workspace:packages/cli-module-info" dependencies: @@ -2948,7 +2948,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-lint@workspace:^, @backstage/cli-module-lint@workspace:packages/cli-module-lint": +"@backstage/cli-module-lint@workspace:*, @backstage/cli-module-lint@workspace:^, @backstage/cli-module-lint@workspace:packages/cli-module-lint": version: 0.0.0-use.local resolution: "@backstage/cli-module-lint@workspace:packages/cli-module-lint" dependencies: @@ -2968,7 +2968,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-maintenance@workspace:^, @backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance": +"@backstage/cli-module-maintenance@workspace:*, @backstage/cli-module-maintenance@workspace:^, @backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance": version: 0.0.0-use.local resolution: "@backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance" dependencies: @@ -2985,7 +2985,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-migrate@workspace:^, @backstage/cli-module-migrate@workspace:packages/cli-module-migrate": +"@backstage/cli-module-migrate@workspace:*, @backstage/cli-module-migrate@workspace:^, @backstage/cli-module-migrate@workspace:packages/cli-module-migrate": version: 0.0.0-use.local resolution: "@backstage/cli-module-migrate@workspace:packages/cli-module-migrate" dependencies: @@ -3005,7 +3005,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-new@workspace:^, @backstage/cli-module-new@workspace:packages/cli-module-new": +"@backstage/cli-module-new@workspace:*, @backstage/cli-module-new@workspace:^, @backstage/cli-module-new@workspace:packages/cli-module-new": version: 0.0.0-use.local resolution: "@backstage/cli-module-new@workspace:packages/cli-module-new" dependencies: @@ -3016,7 +3016,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-test-jest@workspace:^, @backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest": +"@backstage/cli-module-test-jest@workspace:*, @backstage/cli-module-test-jest@workspace:^, @backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest": version: 0.0.0-use.local resolution: "@backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest" dependencies: @@ -3027,7 +3027,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-translations@workspace:^, @backstage/cli-module-translations@workspace:packages/cli-module-translations": +"@backstage/cli-module-translations@workspace:*, @backstage/cli-module-translations@workspace:^, @backstage/cli-module-translations@workspace:packages/cli-module-translations": version: 0.0.0-use.local resolution: "@backstage/cli-module-translations@workspace:packages/cli-module-translations" dependencies: @@ -45616,6 +45616,17 @@ __metadata: resolution: "root@workspace:." dependencies: "@backstage/cli": "workspace:*" + "@backstage/cli-module-auth": "workspace:*" + "@backstage/cli-module-build": "workspace:*" + "@backstage/cli-module-config": "workspace:*" + "@backstage/cli-module-create-github-app": "workspace:*" + "@backstage/cli-module-info": "workspace:*" + "@backstage/cli-module-lint": "workspace:*" + "@backstage/cli-module-maintenance": "workspace:*" + "@backstage/cli-module-migrate": "workspace:*" + "@backstage/cli-module-new": "workspace:*" + "@backstage/cli-module-test-jest": "workspace:*" + "@backstage/cli-module-translations": "workspace:*" "@backstage/codemods": "workspace:*" "@backstage/create-app": "workspace:*" "@backstage/e2e-test-utils": "workspace:*" From 329f394d8281e3a62292aa57d2039c4cdbe4781b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 12:46:37 +0100 Subject: [PATCH 16/45] Start CLI module packages at version 0.0.0 with introductory changeset Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/introduce-cli-modules.md | 15 +++++++++++++++ packages/cli-module-auth/package.json | 2 +- packages/cli-module-build/package.json | 2 +- packages/cli-module-config/package.json | 2 +- .../cli-module-create-github-app/package.json | 2 +- packages/cli-module-info/package.json | 2 +- packages/cli-module-lint/package.json | 2 +- packages/cli-module-maintenance/package.json | 2 +- packages/cli-module-migrate/package.json | 2 +- packages/cli-module-new/package.json | 2 +- packages/cli-module-test-jest/package.json | 2 +- packages/cli-module-translations/package.json | 2 +- 12 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 .changeset/introduce-cli-modules.md diff --git a/.changeset/introduce-cli-modules.md b/.changeset/introduce-cli-modules.md new file mode 100644 index 0000000000..a69df9164b --- /dev/null +++ b/.changeset/introduce-cli-modules.md @@ -0,0 +1,15 @@ +--- +'@backstage/cli-module-auth': minor +'@backstage/cli-module-build': minor +'@backstage/cli-module-config': minor +'@backstage/cli-module-create-github-app': minor +'@backstage/cli-module-info': minor +'@backstage/cli-module-lint': minor +'@backstage/cli-module-maintenance': minor +'@backstage/cli-module-migrate': minor +'@backstage/cli-module-new': minor +'@backstage/cli-module-test-jest': minor +'@backstage/cli-module-translations': minor +--- + +Initial release of the CLI module packages. Each module provides a set of commands that can be discovered automatically by `@backstage/cli` or executed standalone. diff --git a/packages/cli-module-auth/package.json b/packages/cli-module-auth/package.json index c3f4b55d0e..89d04cac00 100644 --- a/packages/cli-module-auth/package.json +++ b/packages/cli-module-auth/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-auth", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index dd59b6948f..0f11c37624 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-build", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-config/package.json b/packages/cli-module-config/package.json index bcf5059280..b73f3d0f71 100644 --- a/packages/cli-module-config/package.json +++ b/packages/cli-module-config/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-config", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-create-github-app/package.json b/packages/cli-module-create-github-app/package.json index 81daa72058..4056cbf28c 100644 --- a/packages/cli-module-create-github-app/package.json +++ b/packages/cli-module-create-github-app/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-create-github-app", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-info/package.json b/packages/cli-module-info/package.json index 50f79da6f0..aafa7908fe 100644 --- a/packages/cli-module-info/package.json +++ b/packages/cli-module-info/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-info", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-lint/package.json b/packages/cli-module-lint/package.json index 50edbae5eb..de42609be9 100644 --- a/packages/cli-module-lint/package.json +++ b/packages/cli-module-lint/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-lint", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-maintenance/package.json b/packages/cli-module-maintenance/package.json index 69888e502f..4293beb4ff 100644 --- a/packages/cli-module-maintenance/package.json +++ b/packages/cli-module-maintenance/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-maintenance", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-migrate/package.json b/packages/cli-module-migrate/package.json index 49faa42261..e29c15fab0 100644 --- a/packages/cli-module-migrate/package.json +++ b/packages/cli-module-migrate/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-migrate", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-new/package.json b/packages/cli-module-new/package.json index a49ccaa6d7..7c6d0ea24d 100644 --- a/packages/cli-module-new/package.json +++ b/packages/cli-module-new/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-new", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-test-jest/package.json b/packages/cli-module-test-jest/package.json index 5fef26bbab..ea5093999a 100644 --- a/packages/cli-module-test-jest/package.json +++ b/packages/cli-module-test-jest/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-test-jest", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" diff --git a/packages/cli-module-translations/package.json b/packages/cli-module-translations/package.json index f9e642afe7..a104dae0d3 100644 --- a/packages/cli-module-translations/package.json +++ b/packages/cli-module-translations/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli-module-translations", - "version": "0.1.0", + "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { "role": "cli-module" From f51e4df2d1d7ee11068d8771f6de4c84bf5189de Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 15:44:54 +0100 Subject: [PATCH 17/45] Fix Prettier formatting and run yarn dedupe Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../cli-module-build/src/lib/bundler/paths.ts | 4 +- .../src/lib/packager/createDistWorkspace.ts | 12 +++--- packages/cli-module-new/src/lib/version.ts | 8 +++- yarn.lock | 38 ++----------------- 4 files changed, 16 insertions(+), 46 deletions(-) diff --git a/packages/cli-module-build/src/lib/bundler/paths.ts b/packages/cli-module-build/src/lib/bundler/paths.ts index 2f2cb0d5d2..d479f74061 100644 --- a/packages/cli-module-build/src/lib/bundler/paths.ts +++ b/packages/cli-module-build/src/lib/bundler/paths.ts @@ -50,9 +50,7 @@ export function resolveBundlingPaths(options: BundlingPathsOptions) { targetHtml = resolvePath(targetDir, `${entry}.html`); if (!fs.pathExistsSync(targetHtml)) { /* eslint-disable-next-line no-restricted-syntax */ - targetHtml = require.resolve( - '@backstage/cli/templates/serve_index.html', - ); + targetHtml = require.resolve('@backstage/cli/templates/serve_index.html'); } } diff --git a/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts index 52ceaaf355..26709788bb 100644 --- a/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts @@ -27,13 +27,11 @@ import partition from 'lodash/partition'; import { run, targetPaths } from '@backstage/cli-common'; -const { - dependencies: cliDependencies, - devDependencies: cliDevDependencies, -} = require('../../../../package.json') as { - dependencies: Record; - devDependencies: Record; -}; +const { dependencies: cliDependencies, devDependencies: cliDevDependencies } = + require('../../../../package.json') as { + dependencies: Record; + devDependencies: Record; + }; import { BuildOptions, buildPackages, diff --git a/packages/cli-module-new/src/lib/version.ts b/packages/cli-module-new/src/lib/version.ts index 57c5646a14..a6f38a38f5 100644 --- a/packages/cli-module-new/src/lib/version.ts +++ b/packages/cli-module-new/src/lib/version.ts @@ -47,9 +47,13 @@ const frontendPluginApi = v('../../../frontend-plugin-api/package.json'); const frontendTestUtils = v('../../../frontend-test-utils/package.json'); const testUtils = v('../../../test-utils/package.json'); const scaffolderNode = v('../../../../plugins/scaffolder-node/package.json'); -const scaffolderNodeTestUtils = v('../../../../plugins/scaffolder-node-test-utils/package.json'); +const scaffolderNodeTestUtils = v( + '../../../../plugins/scaffolder-node-test-utils/package.json', +); const authBackend = v('../../../../plugins/auth-backend/package.json'); -const authBackendModuleGuestProvider = v('../../../../plugins/auth-backend-module-guest-provider/package.json'); +const authBackendModuleGuestProvider = v( + '../../../../plugins/auth-backend-module-guest-provider/package.json', +); const catalogNode = v('../../../../plugins/catalog-node/package.json'); const theme = v('../../../theme/package.json'); const types = v('../../../types/package.json'); diff --git a/yarn.lock b/yarn.lock index a5abf933a3..f67e5a8dae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24933,14 +24933,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10/70fdf883b704d17a5dfc9cde206e698c16bcd74e7f196ab821511651aee4f9f76c9514bdfa6ca3a27b5e49138b89cb222a28caf3afe4567570139577f991df32 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.2.3": +"ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1, ansi-styles@npm:^6.2.3": version: 6.2.3 resolution: "ansi-styles@npm:6.2.3" checksum: 10/c49dad7639f3e48859bd51824c93b9eb0db628afc243c51c3dd2410c4a15ede1a83881c6c7341aa2b159c4f90c11befb38f2ba848c07c66c9f9de4bcd7cb9f30 @@ -32595,14 +32588,7 @@ __metadata: languageName: node linkType: hard -"get-east-asian-width@npm:^1.0.0": - version: 1.2.0 - resolution: "get-east-asian-width@npm:1.2.0" - checksum: 10/c9b280e7c7c67fb89fa17e867c4a9d1c9f1321aba2a9ee27bff37fb6ca9552bccda328c70a80c1f83a0e39ba1b7e3427e60f47823402d19e7a41b83417ec047a - languageName: node - linkType: hard - -"get-east-asian-width@npm:^1.3.1, get-east-asian-width@npm:^1.5.0": +"get-east-asian-width@npm:^1.0.0, get-east-asian-width@npm:^1.3.1, get-east-asian-width@npm:^1.5.0": version: 1.5.0 resolution: "get-east-asian-width@npm:1.5.0" checksum: 10/60bc34cd1e975055ab99f0f177e31bed3e516ff7cee9c536474383954a976abaa6b94a51d99ad158ef1e372790fa096cab7d07f166bb0778f6587954c0fbe946 @@ -32989,20 +32975,13 @@ __metadata: languageName: node linkType: hard -"globals@npm:^17.0.0": +"globals@npm:^17.0.0, globals@npm:^17.3.0": version: 17.4.0 resolution: "globals@npm:17.4.0" checksum: 10/ffad244617e94efcb3da72b7beefc941167c21316148ce378f322db7af72db06468f370e23224b3c7b17b5173a7c75b134e5e7b0949f2828519054a76892508d languageName: node linkType: hard -"globals@npm:^17.3.0": - version: 17.3.0 - resolution: "globals@npm:17.3.0" - checksum: 10/44ba2b7db93eb6a2531dfba09219845e21f2e724a4f400eb59518b180b7d5bcf7f65580530e3d3023d7dc2bdbacf5d265fd87c393f567deb9a2b0472b51c9d5e - languageName: node - linkType: hard - "globalthis@npm:^1.0.1, globalthis@npm:^1.0.3, globalthis@npm:^1.0.4": version: 1.0.4 resolution: "globalthis@npm:1.0.4" @@ -34945,16 +34924,7 @@ __metadata: languageName: node linkType: hard -"is-fullwidth-code-point@npm:^5.0.0": - version: 5.0.0 - resolution: "is-fullwidth-code-point@npm:5.0.0" - dependencies: - get-east-asian-width: "npm:^1.0.0" - checksum: 10/8dfb2d2831b9e87983c136f5c335cd9d14c1402973e357a8ff057904612ed84b8cba196319fabedf9aefe4639e14fe3afe9d9966d1d006ebeb40fe1fed4babe5 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^5.1.0": +"is-fullwidth-code-point@npm:^5.0.0, is-fullwidth-code-point@npm:^5.1.0": version: 5.1.0 resolution: "is-fullwidth-code-point@npm:5.1.0" dependencies: From 7c8bb02ffebcdf713d4297a831b1be64cbd71f9b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 15:59:28 +0100 Subject: [PATCH 18/45] Fix eslint-webpack-plugin version and regenerate lockfile Downgrade eslint-webpack-plugin in cli-module-build from ^5.0.3 to ^4.2.0 to match the main CLI package, preventing @types/eslint from being resolved to v9 which breaks the eslint-plugin TypeScript checks. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-build/package.json | 2 +- yarn.lock | 297 ++++++++++++------------- 2 files changed, 140 insertions(+), 159 deletions(-) diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index 0f11c37624..453ff90a86 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -54,7 +54,7 @@ "ctrlc-windows": "^2.1.0", "esbuild-loader": "^4.4.2", "eslint-rspack-plugin": "^4.2.1", - "eslint-webpack-plugin": "^5.0.3", + "eslint-webpack-plugin": "^4.2.0", "fork-ts-checker-webpack-plugin": "^9.1.0", "fs-extra": "^11.2.0", "glob": "^7.1.7", diff --git a/yarn.lock b/yarn.lock index f67e5a8dae..2b300bf732 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2858,7 +2858,7 @@ __metadata: ctrlc-windows: "npm:^2.1.0" esbuild-loader: "npm:^4.4.2" eslint-rspack-plugin: "npm:^4.2.1" - eslint-webpack-plugin: "npm:^5.0.3" + eslint-webpack-plugin: "npm:^4.2.0" fork-ts-checker-webpack-plugin: "npm:^9.1.0" fs-extra: "npm:^11.2.0" glob: "npm:^7.1.7" @@ -14587,144 +14587,144 @@ __metadata: languageName: node linkType: hard -"@oxc-resolver/binding-android-arm-eabi@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.16.3" +"@oxc-resolver/binding-android-arm-eabi@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.19.1" conditions: os=android & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-android-arm64@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-android-arm64@npm:11.16.3" +"@oxc-resolver/binding-android-arm64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-android-arm64@npm:11.19.1" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-darwin-arm64@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.16.3" +"@oxc-resolver/binding-darwin-arm64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.19.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-darwin-x64@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-darwin-x64@npm:11.16.3" +"@oxc-resolver/binding-darwin-x64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-darwin-x64@npm:11.19.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-freebsd-x64@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.16.3" +"@oxc-resolver/binding-freebsd-x64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.19.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.3" +"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.19.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.3" +"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.19.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.3" +"@oxc-resolver/binding-linux-arm64-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.19.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-musl@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.16.3" +"@oxc-resolver/binding-linux-arm64-musl@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.19.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.3" +"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.19.1" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.3" +"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.19.1" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.3" +"@oxc-resolver/binding-linux-riscv64-musl@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.19.1" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.3" +"@oxc-resolver/binding-linux-s390x-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.19.1" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-gnu@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.16.3" +"@oxc-resolver/binding-linux-x64-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.19.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-musl@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.16.3" +"@oxc-resolver/binding-linux-x64-musl@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.19.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-openharmony-arm64@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.16.3" +"@oxc-resolver/binding-openharmony-arm64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.19.1" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-wasm32-wasi@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.16.3" +"@oxc-resolver/binding-wasm32-wasi@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.19.1" dependencies: "@napi-rs/wasm-runtime": "npm:^1.1.1" conditions: cpu=wasm32 languageName: node linkType: hard -"@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.3" +"@oxc-resolver/binding-win32-arm64-msvc@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.19.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.3" +"@oxc-resolver/binding-win32-ia32-msvc@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.19.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@oxc-resolver/binding-win32-x64-msvc@npm:11.16.3": - version: 11.16.3 - resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.16.3" +"@oxc-resolver/binding-win32-x64-msvc@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.19.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -19236,8 +19236,8 @@ __metadata: linkType: hard "@snyk/dep-graph@npm:^2.12.0": - version: 2.16.3 - resolution: "@snyk/dep-graph@npm:2.16.3" + version: 2.14.0 + resolution: "@snyk/dep-graph@npm:2.14.0" dependencies: event-loop-spinner: "npm:^2.1.0" lodash.clone: "npm:^4.5.0" @@ -19258,7 +19258,7 @@ __metadata: packageurl-js: "npm:2.0.1" semver: "npm:^7.0.0" tslib: "npm:^2" - checksum: 10/609c7946d0f64d4df4e68a3b5e2a61e5739f8b5dc57b42036f1651694fa1cc8d1537bb0e4a9a437a9fcd08c9b5db9d313c4c59a7e1267fb42993a9f41e78e2c6 + checksum: 10/e51882a2e566030a135d2fff477afbc7e4f8a14946089598fe56dd1e9b1b65fffe1ef8b3c8e2ff42629fc01d79b6d5dfeca1c505413731866c5b730728aee0a4 languageName: node linkType: hard @@ -21456,17 +21456,7 @@ __metadata: languageName: node linkType: hard -"@types/eslint@npm:*, @types/eslint@npm:^9.6.1": - version: 9.6.1 - resolution: "@types/eslint@npm:9.6.1" - dependencies: - "@types/estree": "npm:*" - "@types/json-schema": "npm:*" - checksum: 10/719fcd255760168a43d0e306ef87548e1e15bffe361d5f4022b0f266575637acc0ecb85604ac97879ee8ae83c6a6d0613b0ed31d0209ddf22a0fe6d608fc56fe - languageName: node - linkType: hard - -"@types/eslint@npm:^8.56.10": +"@types/eslint@npm:*, @types/eslint@npm:^8.56.10": version: 8.56.12 resolution: "@types/eslint@npm:8.56.12" dependencies: @@ -23123,9 +23113,9 @@ __metadata: languageName: node linkType: hard -"@uiw/codemirror-extensions-basic-setup@npm:4.25.4": - version: 4.25.4 - resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.25.4" +"@uiw/codemirror-extensions-basic-setup@npm:4.25.8": + version: 4.25.8 + resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.25.8" dependencies: "@codemirror/autocomplete": "npm:^6.0.0" "@codemirror/commands": "npm:^6.0.0" @@ -23142,19 +23132,19 @@ __metadata: "@codemirror/search": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 10/8fa523af7cb4ea36db5263221e5a34ecbf18e57ee5c57fbb46f7bfd08ff08523b9fe2c5ae376117d98edaa1a904d1a2966123710e0d866a78ec2d1359955773c + checksum: 10/a8d83465f9f3393b6e95d98ae7f3616ad57f819bce64224831d3db19647524538fc013973074a63551afa69daad9a8ab05f2e5c7441db7e30e722495d7e991d3 languageName: node linkType: hard "@uiw/react-codemirror@npm:^4.9.3": - version: 4.25.4 - resolution: "@uiw/react-codemirror@npm:4.25.4" + version: 4.25.8 + resolution: "@uiw/react-codemirror@npm:4.25.8" dependencies: "@babel/runtime": "npm:^7.18.6" "@codemirror/commands": "npm:^6.1.0" "@codemirror/state": "npm:^6.1.1" "@codemirror/theme-one-dark": "npm:^6.0.0" - "@uiw/codemirror-extensions-basic-setup": "npm:4.25.4" + "@uiw/codemirror-extensions-basic-setup": "npm:4.25.8" codemirror: "npm:^6.0.0" peerDependencies: "@babel/runtime": ">=7.11.0" @@ -23164,7 +23154,7 @@ __metadata: codemirror: ">=6.0.0" react: ">=17.0.0" react-dom: ">=17.0.0" - checksum: 10/679966cfa5cc2e7d5b7c8b40060018bebfc3a2d66492672c64e659e1c719cedd7a10ed7fb3aa014d77c42927581c4ebdf6760ab56568225781798b35dc13b8c6 + checksum: 10/8c974e22dad1ad6231f33f7db42cd5b68caaf9bea545539b06b8a89dda3427eebadf47c8f48ee0d74cdf5a25000a8fcc02bac9fe560b624955eedf1f9bb47a85 languageName: node linkType: hard @@ -30711,23 +30701,6 @@ __metadata: languageName: node linkType: hard -"eslint-webpack-plugin@npm:^5.0.3": - version: 5.0.3 - resolution: "eslint-webpack-plugin@npm:5.0.3" - dependencies: - "@types/eslint": "npm:^9.6.1" - flatted: "npm:^3.3.3" - jest-worker: "npm:^29.7.0" - micromatch: "npm:^4.0.8" - normalize-path: "npm:^3.0.0" - schema-utils: "npm:^4.3.2" - peerDependencies: - eslint: ^8.0.0 || ^9.0.0 - webpack: ^5.0.0 - checksum: 10/fbf86752ad9493ea70ef025a044c1437e105be51c430762ceac9ae930f4e67c9027d7b1b848969fb3abd285e32ce0fd04382d6e8326958be6b1068415bdd38ab - languageName: node - linkType: hard - "eslint@npm:^8.33.0, eslint@npm:^8.6.0": version: 8.57.1 resolution: "eslint@npm:8.57.1" @@ -31310,13 +31283,13 @@ __metadata: linkType: hard "express-rate-limit@npm:^8.2.1, express-rate-limit@npm:^8.2.2": - version: 8.3.0 - resolution: "express-rate-limit@npm:8.3.0" + version: 8.3.1 + resolution: "express-rate-limit@npm:8.3.1" dependencies: ip-address: "npm:10.1.0" peerDependencies: express: ">= 4.11" - checksum: 10/e896a66fecc10639e65873186fdfb71f19d6af650220eb7ea5450725215c3eed8dc6ddcfa1e68a9db8c9facc3326fbc281512ad3ccd8f107f42a2466ce12c18c + checksum: 10/dd97bfc48c01a6d4c5433203232b5e7a1e55e21322bde49033e5f8c4339584fe671a94096144a0810f4ea21dcec8aaaf15823109627e609f8ed1bc5912a345cf languageName: node linkType: hard @@ -31985,7 +31958,7 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^3.1.0, flatted@npm:^3.2.7, flatted@npm:^3.3.3, flatted@npm:^3.3.4": +"flatted@npm:^3.1.0, flatted@npm:^3.2.7, flatted@npm:^3.3.4": version: 3.4.1 resolution: "flatted@npm:3.4.1" checksum: 10/39a308e2ef82d2d8c80ebc74b67d4ff3f668be168137b649440b6735eb9c115d1e0c13ab0d9958b3d2ea9c85087ab7e14c14aa6f625a22b2916d89bbd91bc4a0 @@ -33754,9 +33727,9 @@ __metadata: linkType: hard "hono@npm:^4.11.4": - version: 4.12.5 - resolution: "hono@npm:4.12.5" - checksum: 10/3d03cf2885f7c75325869a178bc94291a17a656002b930dc91456cb177366f6f344c7c90c09707c1fcb4c6e40b1f33fac98f1622628061628cabadcf8cf6d3fd + version: 4.12.7 + resolution: "hono@npm:4.12.7" + checksum: 10/fed37e612730491ba9456f8f68f1b8727a5298cd839fff9641a0b7a95b1e8567a05abb819d32621b40988f166b01140cf7d573c9218dee2741004f48e09564d5 languageName: node linkType: hard @@ -37071,20 +37044,21 @@ __metadata: linkType: hard "knip@npm:^5.42.0": - version: 5.85.0 - resolution: "knip@npm:5.85.0" + version: 5.86.0 + resolution: "knip@npm:5.86.0" dependencies: "@nodelib/fs.walk": "npm:^1.2.3" fast-glob: "npm:^3.3.3" formatly: "npm:^0.3.0" jiti: "npm:^2.6.0" - js-yaml: "npm:^4.1.1" minimist: "npm:^1.2.8" - oxc-resolver: "npm:^11.15.0" + oxc-resolver: "npm:^11.19.1" picocolors: "npm:^1.1.1" picomatch: "npm:^4.0.1" smol-toml: "npm:^1.5.2" strip-json-comments: "npm:5.0.3" + unbash: "npm:^2.2.0" + yaml: "npm:^2.8.2" zod: "npm:^4.1.11" peerDependencies: "@types/node": ">=18" @@ -37092,7 +37066,7 @@ __metadata: bin: knip: bin/knip.js knip-bun: bin/knip-bun.js - checksum: 10/1b80127b24bad3822c2a128e08c30e33db2c716ccb3c1ee19a082d5f04c7d24f049213e15a6369d9449bf60564a86be16e8f986902ba7251bee17a4530c6c954 + checksum: 10/1b8c94f62d2868b0c62499474f462dc09d57e10e73335c01caacff8e0c0b120f441e0881028db30b6a1c185f98a78e2fa727e8faa150bca40c41848263aee04f languageName: node linkType: hard @@ -37300,18 +37274,18 @@ __metadata: linkType: hard "lint-staged@npm:^16.0.0": - version: 16.4.0 - resolution: "lint-staged@npm:16.4.0" + version: 16.3.3 + resolution: "lint-staged@npm:16.3.3" dependencies: commander: "npm:^14.0.3" listr2: "npm:^9.0.5" - picomatch: "npm:^4.0.3" + micromatch: "npm:^4.0.8" string-argv: "npm:^0.3.2" - tinyexec: "npm:^1.0.4" + tinyexec: "npm:^1.0.2" yaml: "npm:^2.8.2" bin: lint-staged: bin/lint-staged.js - checksum: 10/eb7aa0d43e321bbf282ce0c693a3db762aa9b8e5bf29419a49c8877a247cd3a14cf8d519f914f8c8dcd2aea73ac83c0bb44fadb97a30004219e060a780dda74e + checksum: 10/64b20a0aa8710a89db49b4d4384f44e471de8544133cd9f80b1ebeac148144e43b1553aea2b34bf530fd32b554374ee8128c9332033ba138f1a9685964de1cd3 languageName: node linkType: hard @@ -41081,30 +41055,30 @@ __metadata: languageName: node linkType: hard -"oxc-resolver@npm:^11.15.0": - version: 11.16.3 - resolution: "oxc-resolver@npm:11.16.3" +"oxc-resolver@npm:^11.19.1": + version: 11.19.1 + resolution: "oxc-resolver@npm:11.19.1" dependencies: - "@oxc-resolver/binding-android-arm-eabi": "npm:11.16.3" - "@oxc-resolver/binding-android-arm64": "npm:11.16.3" - "@oxc-resolver/binding-darwin-arm64": "npm:11.16.3" - "@oxc-resolver/binding-darwin-x64": "npm:11.16.3" - "@oxc-resolver/binding-freebsd-x64": "npm:11.16.3" - "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.16.3" - "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.16.3" - "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.16.3" - "@oxc-resolver/binding-linux-arm64-musl": "npm:11.16.3" - "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.16.3" - "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.16.3" - "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.16.3" - "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.16.3" - "@oxc-resolver/binding-linux-x64-gnu": "npm:11.16.3" - "@oxc-resolver/binding-linux-x64-musl": "npm:11.16.3" - "@oxc-resolver/binding-openharmony-arm64": "npm:11.16.3" - "@oxc-resolver/binding-wasm32-wasi": "npm:11.16.3" - "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.16.3" - "@oxc-resolver/binding-win32-ia32-msvc": "npm:11.16.3" - "@oxc-resolver/binding-win32-x64-msvc": "npm:11.16.3" + "@oxc-resolver/binding-android-arm-eabi": "npm:11.19.1" + "@oxc-resolver/binding-android-arm64": "npm:11.19.1" + "@oxc-resolver/binding-darwin-arm64": "npm:11.19.1" + "@oxc-resolver/binding-darwin-x64": "npm:11.19.1" + "@oxc-resolver/binding-freebsd-x64": "npm:11.19.1" + "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.19.1" + "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.19.1" + "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-arm64-musl": "npm:11.19.1" + "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.19.1" + "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-x64-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-x64-musl": "npm:11.19.1" + "@oxc-resolver/binding-openharmony-arm64": "npm:11.19.1" + "@oxc-resolver/binding-wasm32-wasi": "npm:11.19.1" + "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.19.1" + "@oxc-resolver/binding-win32-ia32-msvc": "npm:11.19.1" + "@oxc-resolver/binding-win32-x64-msvc": "npm:11.19.1" dependenciesMeta: "@oxc-resolver/binding-android-arm-eabi": optional: true @@ -41146,7 +41120,7 @@ __metadata: optional: true "@oxc-resolver/binding-win32-x64-msvc": optional: true - checksum: 10/2d0da140e34a74347d03a233488ad0284bbb252a6d250b7ca78d5a431d04d72b8275d896b8fb0d03846f221bcbcb2395739187d2645bf84d1d1332b74b7720be + checksum: 10/a6c8fdb2ef4bf9bb84f28e58685457de427d31f74373c0fbd6d1106010cab33027fa3b4336b1b86d0df0a089cd73a6060b730b1b24974d56c59f6fa29c559f9d languageName: node linkType: hard @@ -42760,13 +42734,13 @@ __metadata: linkType: hard "postcss@npm:^8.1.0, postcss@npm:^8.4.33, postcss@npm:^8.5.1, postcss@npm:^8.5.6": - version: 8.5.6 - resolution: "postcss@npm:8.5.6" + version: 8.5.8 + resolution: "postcss@npm:8.5.8" dependencies: nanoid: "npm:^3.3.11" picocolors: "npm:^1.1.1" source-map-js: "npm:^1.2.1" - checksum: 10/9e4fbe97574091e9736d0e82a591e29aa100a0bf60276a926308f8c57249698935f35c5d2f4e80de778d0cbb8dcffab4f383d85fd50c5649aca421c3df729b86 + checksum: 10/cbacbfd7f767e2c820d4bf09a3a744834dd7d14f69ff08d1f57b1a7defce9ae5efcf31981890d9697a972a64e9965de677932ef28e4c8ba23a87aad45b82c459 languageName: node linkType: hard @@ -45931,7 +45905,7 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:^4.0.0, schema-utils@npm:^4.2.0, schema-utils@npm:^4.3.0, schema-utils@npm:^4.3.2, schema-utils@npm:^4.3.3": +"schema-utils@npm:^4.0.0, schema-utils@npm:^4.2.0, schema-utils@npm:^4.3.0, schema-utils@npm:^4.3.3": version: 4.3.3 resolution: "schema-utils@npm:4.3.3" dependencies: @@ -48041,15 +48015,15 @@ __metadata: linkType: hard "tar@npm:^7.4.3, tar@npm:^7.5.6": - version: 7.5.10 - resolution: "tar@npm:7.5.10" + version: 7.5.11 + resolution: "tar@npm:7.5.11" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" minizlib: "npm:^3.1.0" yallist: "npm:^5.0.0" - checksum: 10/98ba6421a250b233c36a54f7441647bdfee1ed0b916cd57850259a3602154d996f5b8422f67ef5c8ce77f582ed938054775c2873fc7c901e0c7530ed50febc40 + checksum: 10/fb2e77ee858a73936c68e066f4a602d428d6f812e6da0cc1e14a41f99498e4f7fd3535e355fa15157240a5538aa416026cfa6306bb0d1d1c1abf314b1f878e9a languageName: node linkType: hard @@ -48384,10 +48358,10 @@ __metadata: languageName: node linkType: hard -"tinyexec@npm:^1.0.4": - version: 1.0.4 - resolution: "tinyexec@npm:1.0.4" - checksum: 10/ccebe4044eef6fa5050929df7862fda70b4fb700f15d94aef8ae6109b9d194dbc3a990125d99944fd25b90fe2115e1927f055b909a604c571a81b647ede5757a +"tinyexec@npm:^1.0.2": + version: 1.0.2 + resolution: "tinyexec@npm:1.0.2" + checksum: 10/cb709ed4240e873d3816e67f851d445f5676e0ae3a52931a60ff571d93d388da09108c8057b62351766133ee05ff3159dd56c3a0fbd39a5933c6639ce8771405 languageName: node linkType: hard @@ -49344,6 +49318,13 @@ __metadata: languageName: node linkType: hard +"unbash@npm:^2.2.0": + version: 2.2.0 + resolution: "unbash@npm:2.2.0" + checksum: 10/dc169c6cacff0364c3d46dbe3f08f4c812cee63359f94ebace483b1a382585d5a1bf4007c12ed3c73671a0256d0026efc23e4732583ae76b42d8570fc4680667 + languageName: node + linkType: hard + "unbox-primitive@npm:^1.1.0": version: 1.1.0 resolution: "unbox-primitive@npm:1.1.0" @@ -49401,9 +49382,9 @@ __metadata: linkType: hard "undici@npm:^7.2.3, undici@npm:^7.22.0": - version: 7.22.0 - resolution: "undici@npm:7.22.0" - checksum: 10/a7a1813ba4b74c0d46cc8dd160386202c05699ffc487c5d882cf40e6d2435c8d6faff3b8f8675d09bd1ef0386e370675c26b59b9a8c8b3f17b9f82a42236a927 + version: 7.24.1 + resolution: "undici@npm:7.24.1" + checksum: 10/0af4ec2fc2ae50b1d0636895793ea2274a89a7cd445690089a1b957c4ac4a0336e48ab9ac48a4e8f5023d4b5eab56368c3f17c75d6b4c81b4281b674d1e60c9f languageName: node linkType: hard @@ -51179,12 +51160,12 @@ __metadata: linkType: soft "yauzl@npm:^3.0.0": - version: 3.2.0 - resolution: "yauzl@npm:3.2.0" + version: 3.2.1 + resolution: "yauzl@npm:3.2.1" dependencies: buffer-crc32: "npm:~0.2.3" pend: "npm:~1.2.0" - checksum: 10/a3cd2bfcf7590673bb35750f2a4e5107e3cc939d32d98a072c0673fe42329e390f471b4a53dbbd72512229099b18aa3b79e6ddb87a73b3a17446080c903a2c4b + checksum: 10/15dfae75fbfe59c6a1b7a2cb27a995cda0ee70549d32d6b19937e84897436170f169f6bbefc34b9e9beb9c9114a1b8a8a40e7687a907909a19681ebcbf35a1f3 languageName: node linkType: hard From 72457cfe98f6ce0a5a8e4f7d8ad7a7f7996ed914 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 16:06:33 +0100 Subject: [PATCH 19/45] Fix incorrect relative package.json paths in cli-module-build Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-build/src/lib/bundler/config.ts | 2 +- .../cli-module-build/src/lib/packager/createDistWorkspace.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli-module-build/src/lib/bundler/config.ts b/packages/cli-module-build/src/lib/bundler/config.ts index 9fbda57f27..77347d66b1 100644 --- a/packages/cli-module-build/src/lib/bundler/config.ts +++ b/packages/cli-module-build/src/lib/bundler/config.ts @@ -32,7 +32,7 @@ import pickBy from 'lodash/pickBy'; import { runOutput, targetPaths } from '@backstage/cli-common'; import { transforms } from './transforms'; -const { version } = require('../../../../package.json') as { version: string }; +const { version } = require('../../../package.json') as { version: string }; import yn from 'yn'; import { hasReactDomClient } from './hasReactDomClient'; import { createWorkspaceLinkingPlugins } from './linkWorkspaces'; diff --git a/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts index 26709788bb..cd9f7657a3 100644 --- a/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts @@ -28,7 +28,7 @@ import partition from 'lodash/partition'; import { run, targetPaths } from '@backstage/cli-common'; const { dependencies: cliDependencies, devDependencies: cliDevDependencies } = - require('../../../../package.json') as { + require('../../../package.json') as { dependencies: Record; devDependencies: Record; }; From 506da6b8be64bed330c91142b9ecabca9ef57ca6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 16:14:54 +0100 Subject: [PATCH 20/45] Fix rollup version in cli-module-build to prevent API report breakage Downgrade rollup from ^4.59.0 to ^4.27.3 to match the main CLI package and avoid the dedupe upgrading all rollup instances to 4.59.0, which breaks API report generation. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-build/package.json | 2 +- yarn.lock | 216 +++++++++++-------------- 2 files changed, 94 insertions(+), 124 deletions(-) diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index 453ff90a86..374fe982d7 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -87,7 +87,7 @@ "@types/npm-packlist": "^3.0.0", "@types/shell-quote": "^1.7.5", "cross-spawn": "^7.0.6", - "rollup": "^4.59.0", + "rollup": "^4.27.3", "ts-morph": "^24.0.0" }, "bin": "bin/cli-module-build" diff --git a/yarn.lock b/yarn.lock index 2b300bf732..1445578ad3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2871,7 +2871,7 @@ __metadata: postcss: "npm:^8.1.0" postcss-import: "npm:^16.1.0" react-dev-utils: "npm:^12.0.0-next.60" - rollup: "npm:^4.59.0" + rollup: "npm:^4.27.3" rollup-plugin-dts: "npm:^6.1.0" rollup-plugin-esbuild: "npm:^6.1.1" rollup-plugin-postcss: "npm:^4.0.0" @@ -17537,177 +17537,156 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.59.0" +"@rollup/rollup-android-arm-eabi@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.53.3" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-android-arm64@npm:4.59.0" +"@rollup/rollup-android-arm64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-android-arm64@npm:4.53.3" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-darwin-arm64@npm:4.59.0" +"@rollup/rollup-darwin-arm64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-darwin-arm64@npm:4.53.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-darwin-x64@npm:4.59.0" +"@rollup/rollup-darwin-x64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-darwin-x64@npm:4.53.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-freebsd-arm64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.59.0" +"@rollup/rollup-freebsd-arm64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.53.3" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-freebsd-x64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-freebsd-x64@npm:4.59.0" +"@rollup/rollup-freebsd-x64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-freebsd-x64@npm:4.53.3" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.59.0" +"@rollup/rollup-linux-arm-gnueabihf@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.53.3" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm-musleabihf@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.59.0" +"@rollup/rollup-linux-arm-musleabihf@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.53.3" conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.59.0" +"@rollup/rollup-linux-arm64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.53.3" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.59.0" +"@rollup/rollup-linux-arm64-musl@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.53.3" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-loong64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.59.0" +"@rollup/rollup-linux-loong64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.53.3" conditions: os=linux & cpu=loong64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-loong64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-loong64-musl@npm:4.59.0" - conditions: os=linux & cpu=loong64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-ppc64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.59.0" +"@rollup/rollup-linux-ppc64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.53.3" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-ppc64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.59.0" - conditions: os=linux & cpu=ppc64 & libc=musl - languageName: node - linkType: hard - -"@rollup/rollup-linux-riscv64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.59.0" +"@rollup/rollup-linux-riscv64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.53.3" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.59.0" +"@rollup/rollup-linux-riscv64-musl@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.53.3" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-s390x-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.59.0" +"@rollup/rollup-linux-s390x-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.53.3" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.59.0" +"@rollup/rollup-linux-x64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.53.3" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.59.0" +"@rollup/rollup-linux-x64-musl@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.53.3" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-openbsd-x64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-openbsd-x64@npm:4.59.0" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@rollup/rollup-openharmony-arm64@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-openharmony-arm64@npm:4.59.0" +"@rollup/rollup-openharmony-arm64@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-openharmony-arm64@npm:4.53.3" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.59.0" +"@rollup/rollup-win32-arm64-msvc@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.53.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.59.0" +"@rollup/rollup-win32-ia32-msvc@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.53.3" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-gnu@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-win32-x64-gnu@npm:4.59.0" +"@rollup/rollup-win32-x64-gnu@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-win32-x64-gnu@npm:4.53.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.59.0": - version: 4.59.0 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.59.0" +"@rollup/rollup-win32-x64-msvc@npm:4.53.3": + version: 4.53.3 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.53.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -45465,35 +45444,32 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.27.3, rollup@npm:^4.43.0, rollup@npm:^4.59.0": - version: 4.59.0 - resolution: "rollup@npm:4.59.0" +"rollup@npm:^4.27.3, rollup@npm:^4.43.0": + version: 4.53.3 + resolution: "rollup@npm:4.53.3" dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.59.0" - "@rollup/rollup-android-arm64": "npm:4.59.0" - "@rollup/rollup-darwin-arm64": "npm:4.59.0" - "@rollup/rollup-darwin-x64": "npm:4.59.0" - "@rollup/rollup-freebsd-arm64": "npm:4.59.0" - "@rollup/rollup-freebsd-x64": "npm:4.59.0" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.59.0" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.59.0" - "@rollup/rollup-linux-arm64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-arm64-musl": "npm:4.59.0" - "@rollup/rollup-linux-loong64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-loong64-musl": "npm:4.59.0" - "@rollup/rollup-linux-ppc64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-ppc64-musl": "npm:4.59.0" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-riscv64-musl": "npm:4.59.0" - "@rollup/rollup-linux-s390x-gnu": "npm:4.59.0" - "@rollup/rollup-linux-x64-gnu": "npm:4.59.0" - "@rollup/rollup-linux-x64-musl": "npm:4.59.0" - "@rollup/rollup-openbsd-x64": "npm:4.59.0" - "@rollup/rollup-openharmony-arm64": "npm:4.59.0" - "@rollup/rollup-win32-arm64-msvc": "npm:4.59.0" - "@rollup/rollup-win32-ia32-msvc": "npm:4.59.0" - "@rollup/rollup-win32-x64-gnu": "npm:4.59.0" - "@rollup/rollup-win32-x64-msvc": "npm:4.59.0" + "@rollup/rollup-android-arm-eabi": "npm:4.53.3" + "@rollup/rollup-android-arm64": "npm:4.53.3" + "@rollup/rollup-darwin-arm64": "npm:4.53.3" + "@rollup/rollup-darwin-x64": "npm:4.53.3" + "@rollup/rollup-freebsd-arm64": "npm:4.53.3" + "@rollup/rollup-freebsd-x64": "npm:4.53.3" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.53.3" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.53.3" + "@rollup/rollup-linux-arm64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-arm64-musl": "npm:4.53.3" + "@rollup/rollup-linux-loong64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-riscv64-musl": "npm:4.53.3" + "@rollup/rollup-linux-s390x-gnu": "npm:4.53.3" + "@rollup/rollup-linux-x64-gnu": "npm:4.53.3" + "@rollup/rollup-linux-x64-musl": "npm:4.53.3" + "@rollup/rollup-openharmony-arm64": "npm:4.53.3" + "@rollup/rollup-win32-arm64-msvc": "npm:4.53.3" + "@rollup/rollup-win32-ia32-msvc": "npm:4.53.3" + "@rollup/rollup-win32-x64-gnu": "npm:4.53.3" + "@rollup/rollup-win32-x64-msvc": "npm:4.53.3" "@types/estree": "npm:1.0.8" fsevents: "npm:~2.3.2" dependenciesMeta: @@ -45519,12 +45495,8 @@ __metadata: optional: true "@rollup/rollup-linux-loong64-gnu": optional: true - "@rollup/rollup-linux-loong64-musl": - optional: true "@rollup/rollup-linux-ppc64-gnu": optional: true - "@rollup/rollup-linux-ppc64-musl": - optional: true "@rollup/rollup-linux-riscv64-gnu": optional: true "@rollup/rollup-linux-riscv64-musl": @@ -45535,8 +45507,6 @@ __metadata: optional: true "@rollup/rollup-linux-x64-musl": optional: true - "@rollup/rollup-openbsd-x64": - optional: true "@rollup/rollup-openharmony-arm64": optional: true "@rollup/rollup-win32-arm64-msvc": @@ -45551,7 +45521,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: 10/728237932aad7022c0640cd126b9fe5285f2578099f22a0542229a17785320a6553b74582fa5977877541c1faf27de65ed2750bc89dbb55b525405244a46d9f1 + checksum: 10/e2eff82405061fa907f15dfbf742b1f5fb4b214495c00989bcdbe21da5fcb3f6dec3deabacec491300a53c99da409586cfc77bdf29b411fccb9089b72cd3728d languageName: node linkType: hard From 86509de5c88973ecf3a94765d07f878f40a2cef7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 16:44:50 +0100 Subject: [PATCH 21/45] Fix CI failures: dependencies, API reports, and create-app versions - Move runtime dependencies from devDependencies to dependencies in cli-module-build, cli-module-auth, cli-module-migrate, cli-module-new, cli-module-test-jest, and cli-module-translations - Fix relative package.json paths in cli-module-build - Downgrade rollup in cli-module-build to ^4.27.3 to match the CLI - Downgrade eslint-webpack-plugin to ^4.2.0 to prevent @types/eslint v9 - Add CLI module packages to create-app version helper - Add allow-warnings for CLI module packages in API reports - Generate API report files for all CLI module packages Signed-off-by: Patrik Oldsberg Made-with: Cursor --- package.json | 2 +- packages/cli-module-auth/package.json | 4 +- packages/cli-module-auth/report.api.md | 13 ++++++ packages/cli-module-build/package.json | 10 ++--- packages/cli-module-build/report.api.md | 16 +++++++ .../src/lib/bundler/config.ts | 2 + .../src/lib/packager/createDistWorkspace.ts | 1 + packages/cli-module-config/report.api.md | 23 ++++++++++ .../report.api.md | 13 ++++++ packages/cli-module-info/report.api.md | 13 ++++++ packages/cli-module-lint/report.api.md | 13 ++++++ packages/cli-module-maintenance/report.api.md | 13 ++++++ packages/cli-module-migrate/package.json | 11 ++++- packages/cli-module-migrate/report.api.md | 13 ++++++ packages/cli-module-new/package.json | 22 ++++++++- packages/cli-module-new/report.api.md | 13 ++++++ packages/cli-module-test-jest/package.json | 4 ++ packages/cli-module-test-jest/report.api.md | 13 ++++++ packages/cli-module-translations/package.json | 9 +++- .../cli-module-translations/report.api.md | 13 ++++++ packages/create-app/src/lib/versions.ts | 22 +++++++++ yarn.lock | 45 ++++++++++++++++--- 22 files changed, 268 insertions(+), 20 deletions(-) create mode 100644 packages/cli-module-auth/report.api.md create mode 100644 packages/cli-module-build/report.api.md create mode 100644 packages/cli-module-config/report.api.md create mode 100644 packages/cli-module-create-github-app/report.api.md create mode 100644 packages/cli-module-info/report.api.md create mode 100644 packages/cli-module-lint/report.api.md create mode 100644 packages/cli-module-maintenance/report.api.md create mode 100644 packages/cli-module-migrate/report.api.md create mode 100644 packages/cli-module-new/report.api.md create mode 100644 packages/cli-module-test-jest/report.api.md create mode 100644 packages/cli-module-translations/report.api.md diff --git a/package.json b/package.json index 962fe132d4..a302681d2f 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "build:all": "backstage-cli repo build --all", "build:api-docs": "LANG=en_EN yarn build:api-reports --docs --exclude 'plugins/@(api-docs|api-docs-module-protoc-gen-doc|app-visualizer|catalog-graph|catalog-import|catalog-unprocessed-entities|config-schema|example-todo-list|example-todo-list-backend)'", "build:api-reports": "yarn build:api-reports:only --tsc", - "build:api-reports:only": "LANG=en_US.UTF-8 NODE_OPTIONS=--max-old-space-size=8192 backstage-repo-tools api-reports --sql-reports --allow-warnings 'packages/backend-app-api,packages/core-components,plugins/+(catalog|catalog-import|kubernetes)' -o ae-undocumented,ae-wrong-input-file-type --validate-release-tags", + "build:api-reports:only": "LANG=en_US.UTF-8 NODE_OPTIONS=--max-old-space-size=8192 backstage-repo-tools api-reports --sql-reports --allow-warnings 'packages/backend-app-api,packages/cli-module-*,packages/core-components,plugins/+(catalog|catalog-import|kubernetes)' -o ae-undocumented,ae-wrong-input-file-type --validate-release-tags", "build:backend": "yarn workspace example-backend build", "build:knip-reports": "backstage-repo-tools knip-reports", "build:plugins-report": "node ./scripts/build-plugins-report", diff --git a/packages/cli-module-auth/package.json b/packages/cli-module-auth/package.json index 89d04cac00..6e4111bf03 100644 --- a/packages/cli-module-auth/package.json +++ b/packages/cli-module-auth/package.json @@ -35,6 +35,7 @@ "@backstage/cli-node": "workspace:^", "@backstage/errors": "workspace:^", "cleye": "^2.3.0", + "cross-fetch": "^4.0.0", "fs-extra": "^11.2.0", "glob": "^7.1.7", "inquirer": "^8.2.0", @@ -46,8 +47,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/fs-extra": "^11.0.0", - "@types/proper-lockfile": "^4", - "cross-fetch": "^4.0.0" + "@types/proper-lockfile": "^4" }, "bin": "bin/cli-module-auth" } diff --git a/packages/cli-module-auth/report.api.md b/packages/cli-module-auth/report.api.md new file mode 100644 index 0000000000..510bcaabe7 --- /dev/null +++ b/packages/cli-module-auth/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-module-auth" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index 374fe982d7..b5232ab955 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -37,6 +37,7 @@ "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/module-federation-common": "workspace:^", "@manypkg/get-packages": "^1.1.3", "@module-federation/enhanced": "^0.21.6", "@pmmmwh/react-refresh-webpack-plugin": "^0.6.2", @@ -51,6 +52,7 @@ "chalk": "^4.0.0", "chokidar": "^3.5.3", "cleye": "^2.3.0", + "cross-spawn": "^7.0.6", "ctrlc-windows": "^2.1.0", "esbuild-loader": "^4.4.2", "eslint-rspack-plugin": "^4.2.1", @@ -67,6 +69,7 @@ "postcss": "^8.1.0", "postcss-import": "^16.1.0", "react-dev-utils": "^12.0.0-next.60", + "rollup": "^4.27.3", "rollup-plugin-dts": "^6.1.0", "rollup-plugin-esbuild": "^6.1.1", "rollup-plugin-postcss": "^4.0.0", @@ -74,6 +77,7 @@ "shell-quote": "^1.8.1", "tar": "^7.5.6", "ts-checker-rspack-plugin": "^1.1.5", + "ts-morph": "^24.0.0", "webpack": "^5.105.4", "webpack-dev-server": "^5.2.3", "yn": "^4.0.0" @@ -81,14 +85,10 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@backstage/module-federation-common": "workspace:^", "@types/fs-extra": "^11.0.0", "@types/lodash": "^4.14.151", "@types/npm-packlist": "^3.0.0", - "@types/shell-quote": "^1.7.5", - "cross-spawn": "^7.0.6", - "rollup": "^4.27.3", - "ts-morph": "^24.0.0" + "@types/shell-quote": "^1.7.5" }, "bin": "bin/cli-module-build" } diff --git a/packages/cli-module-build/report.api.md b/packages/cli-module-build/report.api.md new file mode 100644 index 0000000000..6309f5b839 --- /dev/null +++ b/packages/cli-module-build/report.api.md @@ -0,0 +1,16 @@ +## API Report File for "@backstage/cli-module-build" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// Warning: (ae-missing-release-tag) "buildPlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +const buildPlugin: CliModule; +export { buildPlugin }; +export default buildPlugin; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-build/src/lib/bundler/config.ts b/packages/cli-module-build/src/lib/bundler/config.ts index 77347d66b1..f2fdf84b25 100644 --- a/packages/cli-module-build/src/lib/bundler/config.ts +++ b/packages/cli-module-build/src/lib/bundler/config.ts @@ -32,7 +32,9 @@ import pickBy from 'lodash/pickBy'; import { runOutput, targetPaths } from '@backstage/cli-common'; import { transforms } from './transforms'; + const { version } = require('../../../package.json') as { version: string }; + import yn from 'yn'; import { hasReactDomClient } from './hasReactDomClient'; import { createWorkspaceLinkingPlugins } from './linkWorkspaces'; diff --git a/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts index cd9f7657a3..5930d3b570 100644 --- a/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts @@ -32,6 +32,7 @@ const { dependencies: cliDependencies, devDependencies: cliDevDependencies } = dependencies: Record; devDependencies: Record; }; + import { BuildOptions, buildPackages, diff --git a/packages/cli-module-config/report.api.md b/packages/cli-module-config/report.api.md new file mode 100644 index 0000000000..185bec4e05 --- /dev/null +++ b/packages/cli-module-config/report.api.md @@ -0,0 +1,23 @@ +## API Report File for "@backstage/cli-module-config" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// Warning: (ae-missing-release-tag) "configOption" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const configOption: readonly [ + '--config ', + 'Config files to load instead of app-config.yaml', + (opt: string, opts: string[]) => string[], + string[], +]; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-create-github-app/report.api.md b/packages/cli-module-create-github-app/report.api.md new file mode 100644 index 0000000000..16ff642c69 --- /dev/null +++ b/packages/cli-module-create-github-app/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-module-create-github-app" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-info/report.api.md b/packages/cli-module-info/report.api.md new file mode 100644 index 0000000000..764b16ea47 --- /dev/null +++ b/packages/cli-module-info/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-module-info" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-lint/report.api.md b/packages/cli-module-lint/report.api.md new file mode 100644 index 0000000000..4a861a27a0 --- /dev/null +++ b/packages/cli-module-lint/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-module-lint" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-maintenance/report.api.md b/packages/cli-module-maintenance/report.api.md new file mode 100644 index 0000000000..9eb59483d7 --- /dev/null +++ b/packages/cli-module-maintenance/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-module-maintenance" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-migrate/package.json b/packages/cli-module-migrate/package.json index e29c15fab0..b558cfab19 100644 --- a/packages/cli-module-migrate/package.json +++ b/packages/cli-module-migrate/package.json @@ -34,16 +34,23 @@ "dependencies": { "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/release-manifests": "workspace:^", "@manypkg/get-packages": "^1.1.3", + "chalk": "^4.0.0", "cleye": "^2.3.0", - "fs-extra": "^11.2.0" + "fs-extra": "^11.2.0", + "minimatch": "^10.2.1", + "ora": "^5.3.0", + "replace-in-file": "^7.1.0", + "semver": "^7.5.3" }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@backstage/errors": "workspace:^", "@backstage/test-utils": "workspace:^", "@types/fs-extra": "^11.0.0", + "@types/semver": "^7", "msw": "^1.0.0" }, "bin": "bin/cli-module-migrate" diff --git a/packages/cli-module-migrate/report.api.md b/packages/cli-module-migrate/report.api.md new file mode 100644 index 0000000000..09ed6c902a --- /dev/null +++ b/packages/cli-module-migrate/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-module-migrate" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-new/package.json b/packages/cli-module-new/package.json index 7c6d0ea24d..b3a786d113 100644 --- a/packages/cli-module-new/package.json +++ b/packages/cli-module-new/package.json @@ -32,10 +32,28 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/cli-node": "workspace:^" + "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", + "@backstage/errors": "workspace:^", + "chalk": "^4.0.0", + "cleye": "^2.3.0", + "fs-extra": "^11.2.0", + "handlebars": "^4.7.3", + "inquirer": "^8.2.0", + "lodash": "^4.17.21", + "ora": "^5.3.0", + "recursive-readdir": "^2.2.2", + "semver": "^7.5.3", + "yaml": "^2.0.0", + "zod": "^3.25.76", + "zod-validation-error": "^4.0.2" }, "devDependencies": { - "@backstage/cli": "workspace:^" + "@backstage/cli": "workspace:^", + "@types/fs-extra": "^11.0.0", + "@types/inquirer": "^8", + "@types/lodash": "^4.14.151", + "@types/recursive-readdir": "^2.2.4" }, "bin": "bin/cli-module-new" } diff --git a/packages/cli-module-new/report.api.md b/packages/cli-module-new/report.api.md new file mode 100644 index 0000000000..0a9924e731 --- /dev/null +++ b/packages/cli-module-new/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-module-new" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-test-jest/package.json b/packages/cli-module-test-jest/package.json index ea5093999a..73eabf749e 100644 --- a/packages/cli-module-test-jest/package.json +++ b/packages/cli-module-test-jest/package.json @@ -32,10 +32,14 @@ "test": "backstage-cli package test" }, "dependencies": { + "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^" }, "devDependencies": { "@backstage/cli": "workspace:^" }, + "peerDependencies": { + "jest-cli": "^29.0.0 || ^30.0.0" + }, "bin": "bin/cli-module-test-jest" } diff --git a/packages/cli-module-test-jest/report.api.md b/packages/cli-module-test-jest/report.api.md new file mode 100644 index 0000000000..816df9dcf1 --- /dev/null +++ b/packages/cli-module-test-jest/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-module-test-jest" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-module-translations/package.json b/packages/cli-module-translations/package.json index a104dae0d3..0bb3714889 100644 --- a/packages/cli-module-translations/package.json +++ b/packages/cli-module-translations/package.json @@ -32,10 +32,15 @@ "test": "backstage-cli package test" }, "dependencies": { - "@backstage/cli-node": "workspace:^" + "@backstage/cli-common": "workspace:^", + "@backstage/cli-node": "workspace:^", + "cleye": "^2.3.0", + "fs-extra": "^11.2.0", + "ts-morph": "^24.0.0" }, "devDependencies": { - "@backstage/cli": "workspace:^" + "@backstage/cli": "workspace:^", + "@types/fs-extra": "^11.0.0" }, "bin": "bin/cli-module-translations" } diff --git a/packages/cli-module-translations/report.api.md b/packages/cli-module-translations/report.api.md new file mode 100644 index 0000000000..5e5864bea5 --- /dev/null +++ b/packages/cli-module-translations/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-module-translations" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public (undocumented) +const _default: CliModule; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index db865a2db5..bd19366e55 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -38,6 +38,17 @@ import { version as backendDefaults } from '../../../backend-defaults/package.js import { version as catalogClient } from '../../../catalog-client/package.json'; import { version as catalogModel } from '../../../catalog-model/package.json'; import { version as cli } from '../../../cli/package.json'; +import { version as cliModuleAuth } from '../../../cli-module-auth/package.json'; +import { version as cliModuleBuild } from '../../../cli-module-build/package.json'; +import { version as cliModuleConfig } from '../../../cli-module-config/package.json'; +import { version as cliModuleCreateGithubApp } from '../../../cli-module-create-github-app/package.json'; +import { version as cliModuleInfo } from '../../../cli-module-info/package.json'; +import { version as cliModuleLint } from '../../../cli-module-lint/package.json'; +import { version as cliModuleMaintenance } from '../../../cli-module-maintenance/package.json'; +import { version as cliModuleMigrate } from '../../../cli-module-migrate/package.json'; +import { version as cliModuleNew } from '../../../cli-module-new/package.json'; +import { version as cliModuleTestJest } from '../../../cli-module-test-jest/package.json'; +import { version as cliModuleTranslations } from '../../../cli-module-translations/package.json'; import { version as config } from '../../../config/package.json'; import { version as coreAppApi } from '../../../core-app-api/package.json'; import { version as coreCompatApi } from '../../../core-compat-api/package.json'; @@ -107,6 +118,17 @@ export const packageVersions = { '@backstage/catalog-client': catalogClient, '@backstage/catalog-model': catalogModel, '@backstage/cli': cli, + '@backstage/cli-module-auth': cliModuleAuth, + '@backstage/cli-module-build': cliModuleBuild, + '@backstage/cli-module-config': cliModuleConfig, + '@backstage/cli-module-create-github-app': cliModuleCreateGithubApp, + '@backstage/cli-module-info': cliModuleInfo, + '@backstage/cli-module-lint': cliModuleLint, + '@backstage/cli-module-maintenance': cliModuleMaintenance, + '@backstage/cli-module-migrate': cliModuleMigrate, + '@backstage/cli-module-new': cliModuleNew, + '@backstage/cli-module-test-jest': cliModuleTestJest, + '@backstage/cli-module-translations': cliModuleTranslations, '@backstage/config': config, '@backstage/core-app-api': coreAppApi, '@backstage/core-compat-api': coreCompatApi, diff --git a/yarn.lock b/yarn.lock index 1445578ad3..7c572a7c5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2994,12 +2994,19 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/release-manifests": "workspace:^" "@backstage/test-utils": "workspace:^" "@manypkg/get-packages": "npm:^1.1.3" "@types/fs-extra": "npm:^11.0.0" + "@types/semver": "npm:^7" + chalk: "npm:^4.0.0" cleye: "npm:^2.3.0" fs-extra: "npm:^11.2.0" + minimatch: "npm:^10.2.1" msw: "npm:^1.0.0" + ora: "npm:^5.3.0" + replace-in-file: "npm:^7.1.0" + semver: "npm:^7.5.3" bin: cli-module-migrate: bin/cli-module-migrate languageName: unknown @@ -3010,7 +3017,25 @@ __metadata: resolution: "@backstage/cli-module-new@workspace:packages/cli-module-new" dependencies: "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" + "@backstage/errors": "workspace:^" + "@types/fs-extra": "npm:^11.0.0" + "@types/inquirer": "npm:^8" + "@types/lodash": "npm:^4.14.151" + "@types/recursive-readdir": "npm:^2.2.4" + chalk: "npm:^4.0.0" + cleye: "npm:^2.3.0" + fs-extra: "npm:^11.2.0" + handlebars: "npm:^4.7.3" + inquirer: "npm:^8.2.0" + lodash: "npm:^4.17.21" + ora: "npm:^5.3.0" + recursive-readdir: "npm:^2.2.2" + semver: "npm:^7.5.3" + yaml: "npm:^2.0.0" + zod: "npm:^3.25.76" + zod-validation-error: "npm:^4.0.2" bin: cli-module-new: bin/cli-module-new languageName: unknown @@ -3021,7 +3046,10 @@ __metadata: resolution: "@backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest" dependencies: "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" + peerDependencies: + jest-cli: ^29.0.0 || ^30.0.0 bin: cli-module-test-jest: bin/cli-module-test-jest languageName: unknown @@ -3032,7 +3060,12 @@ __metadata: resolution: "@backstage/cli-module-translations@workspace:packages/cli-module-translations" dependencies: "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" + "@types/fs-extra": "npm:^11.0.0" + cleye: "npm:^2.3.0" + fs-extra: "npm:^11.2.0" + ts-morph: "npm:^24.0.0" bin: cli-module-translations: bin/cli-module-translations languageName: unknown @@ -21642,7 +21675,7 @@ __metadata: languageName: node linkType: hard -"@types/inquirer@npm:^8.1.3": +"@types/inquirer@npm:^8, @types/inquirer@npm:^8.1.3": version: 8.2.12 resolution: "@types/inquirer@npm:8.2.12" dependencies: @@ -22416,7 +22449,7 @@ __metadata: languageName: node linkType: hard -"@types/recursive-readdir@npm:^2.2.0": +"@types/recursive-readdir@npm:^2.2.0, @types/recursive-readdir@npm:^2.2.4": version: 2.2.4 resolution: "@types/recursive-readdir@npm:2.2.4" dependencies: @@ -22513,10 +22546,10 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.1.0": - version: 7.7.0 - resolution: "@types/semver@npm:7.7.0" - checksum: 10/ee4514c6c852b1c38f951239db02f9edeea39f5310fad9396a00b51efa2a2d96b3dfca1ae84c88181ea5b7157c57d32d7ef94edacee36fbf975546396b85ba5b +"@types/semver@npm:^7, @types/semver@npm:^7.1.0": + version: 7.7.1 + resolution: "@types/semver@npm:7.7.1" + checksum: 10/8f09e7e6ca3ded67d78ba7a8f7535c8d9cf8ced83c52e7f3ac3c281fe8c689c3fe475d199d94390dc04fc681d51f2358b430bb7b2e21c62de24f2bee2c719068 languageName: node linkType: hard From 95a5771b47ef66d93bc388ce266ae837c52bbbef Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 16:57:58 +0100 Subject: [PATCH 22/45] Fix remaining undeclared imports in cli-module-new and cli-module-test-jest Add missing devDependencies to cli-module-new and add cleye, yargs, and jest-cli peer dependency to cli-module-test-jest. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-new/package.json | 3 +++ packages/cli-module-test-jest/package.json | 4 +++- packages/cli-module-test-jest/src/commands/package/test.ts | 1 + yarn.lock | 7 ++++++- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/cli-module-new/package.json b/packages/cli-module-new/package.json index b3a786d113..b0d22e1701 100644 --- a/packages/cli-module-new/package.json +++ b/packages/cli-module-new/package.json @@ -49,7 +49,10 @@ "zod-validation-error": "^4.0.2" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/test-utils": "workspace:^", "@types/fs-extra": "^11.0.0", "@types/inquirer": "^8", "@types/lodash": "^4.14.151", diff --git a/packages/cli-module-test-jest/package.json b/packages/cli-module-test-jest/package.json index 73eabf749e..ea927e71ae 100644 --- a/packages/cli-module-test-jest/package.json +++ b/packages/cli-module-test-jest/package.json @@ -33,7 +33,9 @@ }, "dependencies": { "@backstage/cli-common": "workspace:^", - "@backstage/cli-node": "workspace:^" + "@backstage/cli-node": "workspace:^", + "cleye": "^2.3.0", + "yargs": "^17.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^" diff --git a/packages/cli-module-test-jest/src/commands/package/test.ts b/packages/cli-module-test-jest/src/commands/package/test.ts index 035db8272f..6c9ad50e5b 100644 --- a/packages/cli-module-test-jest/src/commands/package/test.ts +++ b/packages/cli-module-test-jest/src/commands/package/test.ts @@ -96,5 +96,6 @@ export default async ({ args }: CliCommandContext) => { process.exit(1); } + // eslint-disable-next-line @backstage/no-undeclared-imports await require('jest').run(args); }; diff --git a/yarn.lock b/yarn.lock index 7c572a7c5a..94af36670b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3016,10 +3016,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/cli-module-new@workspace:packages/cli-module-new" dependencies: + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/test-utils": "workspace:^" "@types/fs-extra": "npm:^11.0.0" "@types/inquirer": "npm:^8" "@types/lodash": "npm:^4.14.151" @@ -3048,6 +3051,8 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" + cleye: "npm:^2.3.0" + yargs: "npm:^17.0.0" peerDependencies: jest-cli: ^29.0.0 || ^30.0.0 bin: @@ -51109,7 +51114,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.2, yargs@npm:^17.1.1, yargs@npm:^17.3.1, yargs@npm:^17.7.1, yargs@npm:^17.7.2": +"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.1.1, yargs@npm:^17.3.1, yargs@npm:^17.7.1, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: From 2fae0356135a91811fefa6530511eb25c6d9e69e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 17:12:41 +0100 Subject: [PATCH 23/45] Move @types packages to devDependencies in cli-module-config and cli-module-create-github-app Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-config/package.json | 4 ++-- packages/cli-module-create-github-app/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cli-module-config/package.json b/packages/cli-module-config/package.json index b73f3d0f71..4c281dcaa3 100644 --- a/packages/cli-module-config/package.json +++ b/packages/cli-module-config/package.json @@ -38,7 +38,6 @@ "@backstage/config-loader": "workspace:^", "@backstage/types": "workspace:^", "@manypkg/get-packages": "^1.1.3", - "@types/json-schema": "^7.0.6", "chalk": "^4.0.0", "cleye": "^2.3.0", "json-schema": "^0.4.0", @@ -46,7 +45,8 @@ "yaml": "^2.0.0" }, "devDependencies": { - "@backstage/cli": "workspace:^" + "@backstage/cli": "workspace:^", + "@types/json-schema": "^7.0.6" }, "bin": "bin/cli-module-config" } diff --git a/packages/cli-module-create-github-app/package.json b/packages/cli-module-create-github-app/package.json index 4056cbf28c..9b342a4551 100644 --- a/packages/cli-module-create-github-app/package.json +++ b/packages/cli-module-create-github-app/package.json @@ -35,7 +35,6 @@ "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^", "@octokit/request": "^8.0.0", - "@types/express": "^4.17.6", "chalk": "^4.0.0", "cleye": "^2.3.0", "express": "^4.22.0", @@ -46,6 +45,7 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", + "@types/express": "^4.17.6", "@types/fs-extra": "^11.0.0" }, "bin": "bin/cli-module-create-github-app" From f100c26c920fa1158b3942a541d6814fc4c28dc7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Mar 2026 20:25:16 +0100 Subject: [PATCH 24/45] Fix relative paths in cli-module-translations test The test file was moved from packages/cli/src/modules/translations/lib/ to packages/cli-module-translations/src/lib/ but the relative paths to the repo root tsconfig.json and test fixtures were not updated. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../src/lib/extractTranslations.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/cli-module-translations/src/lib/extractTranslations.test.ts b/packages/cli-module-translations/src/lib/extractTranslations.test.ts index 20ff05b69e..13a94f3a0a 100644 --- a/packages/cli-module-translations/src/lib/extractTranslations.test.ts +++ b/packages/cli-module-translations/src/lib/extractTranslations.test.ts @@ -23,11 +23,11 @@ import { describe('extractTranslations', () => { it('extracts translation refs from the org plugin', () => { const project = createTranslationProject( - resolvePath(__dirname, '../../../../../../tsconfig.json'), + resolvePath(__dirname, '../../../../tsconfig.json'), ); const sourceFile = project.addSourceFileAtPath( - resolvePath(__dirname, '../../../../../..', 'plugins/org/src/alpha.tsx'), + resolvePath(__dirname, '../../../..', 'plugins/org/src/alpha.tsx'), ); const refs = extractTranslationRefsFromSourceFile( @@ -59,12 +59,12 @@ describe('extractTranslations', () => { it('ignores non-TranslationRef exports', () => { const project = createTranslationProject( - resolvePath(__dirname, '../../../../../../tsconfig.json'), + resolvePath(__dirname, '../../../../tsconfig.json'), ); // The main entry of org plugin exports components but no translation ref const sourceFile = project.addSourceFileAtPath( - resolvePath(__dirname, '../../../../../..', 'plugins/org/src/index.ts'), + resolvePath(__dirname, '../../../..', 'plugins/org/src/index.ts'), ); const refs = extractTranslationRefsFromSourceFile( @@ -78,13 +78,13 @@ describe('extractTranslations', () => { it('extracts from the test fixtures translation ref', () => { const project = createTranslationProject( - resolvePath(__dirname, '../../../../../../tsconfig.json'), + resolvePath(__dirname, '../../../../tsconfig.json'), ); const sourceFile = project.addSourceFileAtPath( resolvePath( __dirname, - '../../../../../..', + '../../../..', 'packages/frontend-plugin-api/src/translation/__fixtures__/refs.ts', ), ); From 935c646e897a5b1e976927f807998abc860e8dde Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 01:12:43 +0100 Subject: [PATCH 25/45] Fix CLI module discovery and create-app test mock Resolve CLI module entry points relative to the target project root rather than relying on bare module name resolution. This ensures modules are found even when the CLI package is symlinked from a separate location, such as in the E2E test workspace setup. Also add the missing cli-module-* entries to the create-app tasks test mock that were omitted in a previous commit. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli/src/index.ts | 4 ++-- packages/cli/src/wiring/discoverCliModules.ts | 9 ++++++--- packages/create-app/src/lib/tasks.test.ts | 11 +++++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 489287c3f2..f5056f8ba3 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -24,8 +24,8 @@ import { discoverCliModules } from './wiring/discoverCliModules'; const discoveredModules = discoverCliModules(); if (discoveredModules.length > 0) { - for (const moduleName of discoveredModules) { - initializer.add(import(moduleName)); + for (const resolvedPath of discoveredModules) { + initializer.add(import(resolvedPath)); } } else { // No CLI modules found in the project root; fall back to the built-in diff --git a/packages/cli/src/wiring/discoverCliModules.ts b/packages/cli/src/wiring/discoverCliModules.ts index dac80c1344..fb5e8c7469 100644 --- a/packages/cli/src/wiring/discoverCliModules.ts +++ b/packages/cli/src/wiring/discoverCliModules.ts @@ -23,8 +23,10 @@ import { resolve as resolvePath } from 'node:path'; * Scans the target project root's package.json for dependencies that are CLI * modules (packages with `backstage.role === 'cli-module'`). * - * Returns the names of discovered CLI module packages, or an empty array if - * none are found or the project root cannot be read. + * Returns the resolved entry point paths of discovered CLI module packages, + * or an empty array if none are found or the project root cannot be read. + * The paths are resolved relative to the project root to ensure they can be + * imported regardless of where the CLI code itself is located. */ export function discoverCliModules(): string[] { const rootDir = targetPaths.rootDir; @@ -54,7 +56,8 @@ export function discoverCliModules(): string[] { }); const depPkg = JSON.parse(fs.readFileSync(depPkgPath, 'utf8')); if (PackageRoles.getRoleFromPackage(depPkg) === 'cli-module') { - modules.push(depName); + const resolvedPath = require.resolve(depName, { paths: [rootDir] }); + modules.push(resolvedPath); } } catch { // Skip packages that can't be resolved or read diff --git a/packages/create-app/src/lib/tasks.test.ts b/packages/create-app/src/lib/tasks.test.ts index be6852e3ab..0115790b81 100644 --- a/packages/create-app/src/lib/tasks.test.ts +++ b/packages/create-app/src/lib/tasks.test.ts @@ -50,6 +50,17 @@ jest.mock('./versions', () => ({ packageVersions: { root: '1.2.3', '@backstage/cli': '1.0.0', + '@backstage/cli-module-auth': '1.0.0', + '@backstage/cli-module-build': '1.0.0', + '@backstage/cli-module-config': '1.0.0', + '@backstage/cli-module-create-github-app': '1.0.0', + '@backstage/cli-module-info': '1.0.0', + '@backstage/cli-module-lint': '1.0.0', + '@backstage/cli-module-maintenance': '1.0.0', + '@backstage/cli-module-migrate': '1.0.0', + '@backstage/cli-module-new': '1.0.0', + '@backstage/cli-module-test-jest': '1.0.0', + '@backstage/cli-module-translations': '1.0.0', '@backstage/backend-defaults': '1.0.0', '@backstage/backend-tasks': '1.0.0', '@backstage/catalog-model': '1.0.0', From 99af21a711a2c2f34714bb74490260510af2dbbd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 01:26:54 +0100 Subject: [PATCH 26/45] Add stderr logging to E2E plugin creation step Capture and print stdout and stderr when the plugin creation command fails, so that the actual error is visible in CI logs. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/e2e-test/src/commands/runCommand.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/e2e-test/src/commands/runCommand.ts b/packages/e2e-test/src/commands/runCommand.ts index da39351400..b5d951017d 100644 --- a/packages/e2e-test/src/commands/runCommand.ts +++ b/packages/e2e-test/src/commands/runCommand.ts @@ -383,12 +383,22 @@ async function createPlugin(options: { try { let stdout = ''; + let stderr = ''; child.stdout?.on('data', (data: Buffer) => { stdout = stdout + data.toString('utf8'); }); + child.stderr?.on('data', (data: Buffer) => { + stderr = stderr + data.toString('utf8'); + }); print('Waiting for plugin create script to be done'); - await child.waitForExit(); + try { + await child.waitForExit(); + } catch (error) { + print(`stdout: ${stdout}`); + print(`stderr: ${stderr}`); + throw error; + } const pluginDir = resolvePath( appDir, From 2c952496bf1432552f314f8172219f6520f00434 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 01:40:26 +0100 Subject: [PATCH 27/45] Use static imports for version extraction in cli-module-new Convert dynamic require() calls to static import statements so that Rollup can inline the version values at build time. The cli-module role uses preserveModules in Rollup, which cannot resolve dynamic requires. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-new/src/lib/version.ts | 51 ++++++++++------------ 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/packages/cli-module-new/src/lib/version.ts b/packages/cli-module-new/src/lib/version.ts index a6f38a38f5..fd65135f4c 100644 --- a/packages/cli-module-new/src/lib/version.ts +++ b/packages/cli-module-new/src/lib/version.ts @@ -30,34 +30,29 @@ This does not create an actual dependency on these packages and does not bring i Rollup will extract the value of the version field in each package at build time without leaving any imports in place. */ -type Pkg = { version: string }; -const v = (path: string) => (require(path) as Pkg).version; -const backendPluginApi = v('../../../backend-plugin-api/package.json'); -const backendTestUtils = v('../../../backend-test-utils/package.json'); -const catalogClient = v('../../../catalog-client/package.json'); -const cli = v('../../../cli/package.json'); -const config = v('../../../config/package.json'); -const coreAppApi = v('../../../core-app-api/package.json'); -const coreComponents = v('../../../core-components/package.json'); -const corePluginApi = v('../../../core-plugin-api/package.json'); -const devUtils = v('../../../dev-utils/package.json'); -const errors = v('../../../errors/package.json'); -const frontendDefaults = v('../../../frontend-defaults/package.json'); -const frontendPluginApi = v('../../../frontend-plugin-api/package.json'); -const frontendTestUtils = v('../../../frontend-test-utils/package.json'); -const testUtils = v('../../../test-utils/package.json'); -const scaffolderNode = v('../../../../plugins/scaffolder-node/package.json'); -const scaffolderNodeTestUtils = v( - '../../../../plugins/scaffolder-node-test-utils/package.json', -); -const authBackend = v('../../../../plugins/auth-backend/package.json'); -const authBackendModuleGuestProvider = v( - '../../../../plugins/auth-backend-module-guest-provider/package.json', -); -const catalogNode = v('../../../../plugins/catalog-node/package.json'); -const theme = v('../../../theme/package.json'); -const types = v('../../../types/package.json'); -const backendDefaults = v('../../../backend-defaults/package.json'); + +import { version as backendDefaults } from '../../../backend-defaults/package.json'; +import { version as backendPluginApi } from '../../../backend-plugin-api/package.json'; +import { version as backendTestUtils } from '../../../backend-test-utils/package.json'; +import { version as catalogClient } from '../../../catalog-client/package.json'; +import { version as cli } from '../../../cli/package.json'; +import { version as config } from '../../../config/package.json'; +import { version as coreAppApi } from '../../../core-app-api/package.json'; +import { version as coreComponents } from '../../../core-components/package.json'; +import { version as corePluginApi } from '../../../core-plugin-api/package.json'; +import { version as devUtils } from '../../../dev-utils/package.json'; +import { version as errors } from '../../../errors/package.json'; +import { version as frontendDefaults } from '../../../frontend-defaults/package.json'; +import { version as frontendPluginApi } from '../../../frontend-plugin-api/package.json'; +import { version as frontendTestUtils } from '../../../frontend-test-utils/package.json'; +import { version as testUtils } from '../../../test-utils/package.json'; +import { version as theme } from '../../../theme/package.json'; +import { version as types } from '../../../types/package.json'; +import { version as authBackend } from '../../../../plugins/auth-backend/package.json'; +import { version as authBackendModuleGuestProvider } from '../../../../plugins/auth-backend-module-guest-provider/package.json'; +import { version as catalogNode } from '../../../../plugins/catalog-node/package.json'; +import { version as scaffolderNode } from '../../../../plugins/scaffolder-node/package.json'; +import { version as scaffolderNodeTestUtils } from '../../../../plugins/scaffolder-node-test-utils/package.json'; export const packageVersions: Record = { '@backstage/backend-defaults': backendDefaults, From ff593fa8fa4b07655409610bacc217139cf6c9a7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 02:11:14 +0100 Subject: [PATCH 28/45] Capture stderr in E2E plugin creation step Keep stderr capture from the plugin creation child process to aid debugging if the command fails in the future. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/e2e-test/src/commands/runCommand.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/e2e-test/src/commands/runCommand.ts b/packages/e2e-test/src/commands/runCommand.ts index b5d951017d..a86e7f303d 100644 --- a/packages/e2e-test/src/commands/runCommand.ts +++ b/packages/e2e-test/src/commands/runCommand.ts @@ -392,13 +392,7 @@ async function createPlugin(options: { }); print('Waiting for plugin create script to be done'); - try { - await child.waitForExit(); - } catch (error) { - print(`stdout: ${stdout}`); - print(`stderr: ${stderr}`); - throw error; - } + await child.waitForExit(); const pluginDir = resolvePath( appDir, From 9937a8aa8e81a2b31de0c7b40aaf1351b3082029 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 12:40:25 +0100 Subject: [PATCH 29/45] Clean up CLI module dependencies and revert incorrect require() changes Align dependency versions in CLI modules to match the original CLI package versions. Move dependencies that are only used by modules out of the main CLI package, and add missing dependencies to the modules that actually use them. Revert import-to-require conversions in cli-module-build that were incorrectly introduced during the split. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-auth/package.json | 3 + packages/cli-module-build/package.json | 25 +- .../src/lib/bundler/config.ts | 4 +- .../src/lib/packager/createDistWorkspace.ts | 11 +- packages/cli-module-lint/package.json | 3 +- packages/cli-module-new/package.json | 4 +- packages/cli-module-test-jest/package.json | 2 +- packages/cli/package.json | 138 +------- yarn.lock | 328 +++--------------- 9 files changed, 73 insertions(+), 445 deletions(-) diff --git a/packages/cli-module-auth/package.json b/packages/cli-module-auth/package.json index 6e4111bf03..c3e2d47224 100644 --- a/packages/cli-module-auth/package.json +++ b/packages/cli-module-auth/package.json @@ -49,5 +49,8 @@ "@types/fs-extra": "^11.0.0", "@types/proper-lockfile": "^4" }, + "optionalDependencies": { + "keytar": "^7.9.0" + }, "bin": "bin/cli-module-auth" } diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index b5232ab955..7591007756 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -40,7 +40,7 @@ "@backstage/module-federation-common": "workspace:^", "@manypkg/get-packages": "^1.1.3", "@module-federation/enhanced": "^0.21.6", - "@pmmmwh/react-refresh-webpack-plugin": "^0.6.2", + "@pmmmwh/react-refresh-webpack-plugin": "^0.6.0", "@rollup/plugin-commonjs": "^26.0.0", "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^15.0.0", @@ -49,37 +49,46 @@ "@rspack/dev-server": "^1.1.4", "@rspack/plugin-react-refresh": "^1.4.3", "bfj": "^9.0.2", + "buffer": "^6.0.3", "chalk": "^4.0.0", - "chokidar": "^3.5.3", + "chokidar": "^3.3.1", "cleye": "^2.3.0", - "cross-spawn": "^7.0.6", + "cross-spawn": "^7.0.3", + "css-loader": "^6.5.1", "ctrlc-windows": "^2.1.0", - "esbuild-loader": "^4.4.2", + "esbuild-loader": "^4.0.0", "eslint-rspack-plugin": "^4.2.1", "eslint-webpack-plugin": "^4.2.0", - "fork-ts-checker-webpack-plugin": "^9.1.0", + "fork-ts-checker-webpack-plugin": "^9.0.0", "fs-extra": "^11.2.0", "glob": "^7.1.7", "html-webpack-plugin": "^5.6.3", "lodash": "^4.17.21", - "mini-css-extract-plugin": "^2.10.1", + "mini-css-extract-plugin": "^2.4.2", "node-stdlib-browser": "^1.3.1", "npm-packlist": "^5.0.0", "p-queue": "^6.6.2", "postcss": "^8.1.0", "postcss-import": "^16.1.0", + "process": "^0.11.10", + "raw-loader": "^4.0.2", "react-dev-utils": "^12.0.0-next.60", + "react-refresh": "^0.18.0", "rollup": "^4.27.3", "rollup-plugin-dts": "^6.1.0", "rollup-plugin-esbuild": "^6.1.1", "rollup-plugin-postcss": "^4.0.0", "rollup-pluginutils": "^2.8.2", "shell-quote": "^1.8.1", + "style-loader": "^3.3.1", + "swc-loader": "^0.2.3", "tar": "^7.5.6", "ts-checker-rspack-plugin": "^1.1.5", "ts-morph": "^24.0.0", - "webpack": "^5.105.4", - "webpack-dev-server": "^5.2.3", + "util": "^0.12.3", + "webpack": "~5.105.0", + "webpack-dev-server": "^5.0.0", + "yml-loader": "^2.1.0", "yn": "^4.0.0" }, "devDependencies": { diff --git a/packages/cli-module-build/src/lib/bundler/config.ts b/packages/cli-module-build/src/lib/bundler/config.ts index f2fdf84b25..08856cd63e 100644 --- a/packages/cli-module-build/src/lib/bundler/config.ts +++ b/packages/cli-module-build/src/lib/bundler/config.ts @@ -32,9 +32,7 @@ import pickBy from 'lodash/pickBy'; import { runOutput, targetPaths } from '@backstage/cli-common'; import { transforms } from './transforms'; - -const { version } = require('../../../package.json') as { version: string }; - +import { version } from '../../../package.json'; import yn from 'yn'; import { hasReactDomClient } from './hasReactDomClient'; import { createWorkspaceLinkingPlugins } from './linkWorkspaces'; diff --git a/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts index 5930d3b570..535d54f9dc 100644 --- a/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli-module-build/src/lib/packager/createDistWorkspace.ts @@ -26,13 +26,10 @@ import * as tar from 'tar'; import partition from 'lodash/partition'; import { run, targetPaths } from '@backstage/cli-common'; - -const { dependencies: cliDependencies, devDependencies: cliDevDependencies } = - require('../../../package.json') as { - dependencies: Record; - devDependencies: Record; - }; - +import { + dependencies as cliDependencies, + devDependencies as cliDevDependencies, +} from '../../../package.json'; import { BuildOptions, buildPackages, diff --git a/packages/cli-module-lint/package.json b/packages/cli-module-lint/package.json index de42609be9..e6b9615e39 100644 --- a/packages/cli-module-lint/package.json +++ b/packages/cli-module-lint/package.json @@ -37,8 +37,9 @@ "chalk": "^4.0.0", "cleye": "^2.3.0", "eslint": "^8.6.0", + "eslint-formatter-friendly": "^7.0.0", "fs-extra": "^11.2.0", - "globby": "^11.0.0", + "globby": "^11.1.0", "shell-quote": "^1.8.1" }, "devDependencies": { diff --git a/packages/cli-module-new/package.json b/packages/cli-module-new/package.json index b0d22e1701..bd056c507c 100644 --- a/packages/cli-module-new/package.json +++ b/packages/cli-module-new/package.json @@ -54,9 +54,9 @@ "@backstage/core-plugin-api": "workspace:^", "@backstage/test-utils": "workspace:^", "@types/fs-extra": "^11.0.0", - "@types/inquirer": "^8", + "@types/inquirer": "^8.1.3", "@types/lodash": "^4.14.151", - "@types/recursive-readdir": "^2.2.4" + "@types/recursive-readdir": "^2.2.0" }, "bin": "bin/cli-module-new" } diff --git a/packages/cli-module-test-jest/package.json b/packages/cli-module-test-jest/package.json index ea927e71ae..b02167a934 100644 --- a/packages/cli-module-test-jest/package.json +++ b/packages/cli-module-test-jest/package.json @@ -35,7 +35,7 @@ "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^", "cleye": "^2.3.0", - "yargs": "^17.0.0" + "yargs": "^16.2.0" }, "devDependencies": { "@backstage/cli": "workspace:^" diff --git a/packages/cli/package.json b/packages/cli/package.json index 189fd8faaa..059737a6f3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -47,7 +47,6 @@ ] }, "dependencies": { - "@backstage/catalog-model": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/cli-module-auth": "workspace:^", "@backstage/cli-module-build": "workspace:^", @@ -61,47 +60,21 @@ "@backstage/cli-module-test-jest": "workspace:^", "@backstage/cli-module-translations": "workspace:^", "@backstage/cli-node": "workspace:^", - "@backstage/config": "workspace:^", - "@backstage/config-loader": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/eslint-plugin": "workspace:^", - "@backstage/integration": "workspace:^", - "@backstage/module-federation-common": "workspace:^", - "@backstage/release-manifests": "workspace:^", - "@backstage/types": "workspace:^", "@manypkg/get-packages": "^1.1.3", - "@module-federation/enhanced": "^0.21.6", - "@octokit/request": "^8.0.0", - "@rollup/plugin-commonjs": "^26.0.0", - "@rollup/plugin-json": "^6.0.0", - "@rollup/plugin-node-resolve": "^15.0.0", - "@rollup/plugin-yaml": "^4.0.0", - "@rspack/core": "^1.4.11", - "@rspack/dev-server": "^1.1.4", - "@rspack/plugin-react-refresh": "^1.4.3", "@spotify/eslint-config-base": "^15.0.0", "@spotify/eslint-config-react": "^15.0.0", "@spotify/eslint-config-typescript": "^15.0.0", "@swc/core": "^1.15.6", - "@swc/helpers": "^0.5.17", "@swc/jest": "^0.2.39", - "@types/webpack-env": "^1.15.2", "@typescript-eslint/eslint-plugin": "^8.17.0", "@typescript-eslint/parser": "^8.16.0", - "bfj": "^9.0.2", - "buffer": "^6.0.3", "chalk": "^4.0.0", - "chokidar": "^3.3.1", - "cleye": "^2.3.0", "commander": "^14.0.3", "cross-fetch": "^4.0.0", - "cross-spawn": "^7.0.3", - "css-loader": "^6.5.1", - "ctrlc-windows": "^2.1.0", - "esbuild": "^0.27.0", "eslint": "^8.6.0", "eslint-config-prettier": "^9.0.0", - "eslint-formatter-friendly": "^7.0.0", "eslint-plugin-deprecation": "^3.0.0", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.9.0", @@ -109,55 +82,13 @@ "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-unused-imports": "^4.1.4", - "eslint-rspack-plugin": "^4.2.1", - "express": "^4.22.0", "fs-extra": "^11.2.0", - "git-url-parse": "^15.0.0", "glob": "^7.1.7", - "global-agent": "^3.0.0", - "globby": "^11.1.0", - "handlebars": "^4.7.3", - "html-webpack-plugin": "^5.6.3", - "inquirer": "^8.2.0", "jest-css-modules": "^2.1.0", - "json-schema": "^0.4.0", - "lodash": "^4.17.21", - "minimatch": "^10.2.1", - "node-stdlib-browser": "^1.3.1", - "npm-packlist": "^5.0.0", - "ora": "^5.3.0", - "p-queue": "^6.6.2", "pirates": "^4.0.6", "postcss": "^8.1.0", - "postcss-import": "^16.1.0", - "process": "^0.11.10", - "proper-lockfile": "^4.1.2", - "raw-loader": "^4.0.2", - "react-dev-utils": "^12.0.0-next.60", - "react-refresh": "^0.18.0", - "recursive-readdir": "^2.2.2", - "replace-in-file": "^7.1.0", - "rollup": "^4.27.3", - "rollup-plugin-dts": "^6.1.0", - "rollup-plugin-esbuild": "^6.1.1", - "rollup-plugin-postcss": "^4.0.0", - "rollup-pluginutils": "^2.8.2", - "semver": "^7.5.3", - "shell-quote": "^1.8.1", - "style-loader": "^3.3.1", "sucrase": "^3.20.2", - "swc-loader": "^0.2.3", - "tar": "^7.5.6", - "ts-checker-rspack-plugin": "^1.1.5", - "ts-morph": "^24.0.0", - "undici": "^7.2.3", - "util": "^0.12.3", - "yaml": "^2.0.0", - "yargs": "^16.2.0", - "yml-loader": "^2.1.0", - "yn": "^4.0.0", - "zod": "^3.25.76", - "zod-validation-error": "^4.0.2" + "yaml": "^2.0.0" }, "devDependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -177,91 +108,28 @@ "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", "@jest/environment-jsdom-abstract": "^30.0.0", - "@pmmmwh/react-refresh-webpack-plugin": "^0.6.0", - "@types/cross-spawn": "^6.0.2", - "@types/ejs": "^3.1.3", - "@types/express": "^4.17.6", "@types/fs-extra": "^11.0.0", - "@types/http-proxy": "^1.17.4", - "@types/inquirer": "^8.1.3", "@types/jest": "^30.0.0", "@types/node": "^22.13.14", - "@types/npm-packlist": "^3.0.0", - "@types/proper-lockfile": "^4", - "@types/recursive-readdir": "^2.2.0", - "@types/rollup-plugin-peer-deps-external": "^2.2.0", - "@types/rollup-plugin-postcss": "^3.1.4", - "@types/shell-quote": "^1.7.5", - "@types/svgo": "^2.6.2", - "@types/terser-webpack-plugin": "^5.0.4", - "@types/webpack-sources": "^3.2.3", - "del": "^8.0.0", - "esbuild-loader": "^4.0.0", - "eslint-webpack-plugin": "^4.2.0", - "fork-ts-checker-webpack-plugin": "^9.0.0", "jest": "^30.2.0", "jsdom": "^27.1.0", - "mini-css-extract-plugin": "^2.4.2", - "msw": "^1.0.0", - "nodemon": "^3.0.1", - "terser-webpack-plugin": "^5.1.3", - "webpack": "~5.105.0", - "webpack-dev-server": "^5.0.0" - }, - "optionalDependencies": { - "keytar": "^7.9.0" + "nodemon": "^3.0.1" }, "peerDependencies": { "@jest/environment-jsdom-abstract": "^30.0.0", - "@module-federation/enhanced": "^0.21.6", - "@pmmmwh/react-refresh-webpack-plugin": "^0.6.0", - "esbuild-loader": "^4.0.0", - "eslint-webpack-plugin": "^4.2.0", - "fork-ts-checker-webpack-plugin": "^9.0.0", "jest": "^29.0.0 || ^30.0.0", "jest-environment-jsdom": "*", - "jsdom": "^27.1.0", - "mini-css-extract-plugin": "^2.4.2", - "terser-webpack-plugin": "^5.1.3", - "webpack": "~5.105.0", - "webpack-dev-server": "^5.0.0" + "jsdom": "^27.1.0" }, "peerDependenciesMeta": { "@jest/environment-jsdom-abstract": { "optional": true }, - "@module-federation/enhanced": { - "optional": true - }, - "@pmmmwh/react-refresh-webpack-plugin": { - "optional": true - }, - "esbuild-loader": { - "optional": true - }, - "eslint-webpack-plugin": { - "optional": true - }, - "fork-ts-checker-webpack-plugin": { - "optional": true - }, "jest-environment-jsdom": { "optional": true }, "jsdom": { "optional": true - }, - "mini-css-extract-plugin": { - "optional": true - }, - "terser-webpack-plugin": { - "optional": true - }, - "webpack": { - "optional": true - }, - "webpack-dev-server": { - "optional": true } }, "configSchema": { diff --git a/yarn.lock b/yarn.lock index 94af36670b..d470627b63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2816,9 +2816,13 @@ __metadata: fs-extra: "npm:^11.2.0" glob: "npm:^7.1.7" inquirer: "npm:^8.2.0" + keytar: "npm:^7.9.0" proper-lockfile: "npm:^4.1.2" yaml: "npm:^2.0.0" zod: "npm:^3.25.76" + dependenciesMeta: + keytar: + optional: true bin: cli-module-auth: bin/cli-module-auth languageName: unknown @@ -2838,7 +2842,7 @@ __metadata: "@backstage/module-federation-common": "workspace:^" "@manypkg/get-packages": "npm:^1.1.3" "@module-federation/enhanced": "npm:^0.21.6" - "@pmmmwh/react-refresh-webpack-plugin": "npm:^0.6.2" + "@pmmmwh/react-refresh-webpack-plugin": "npm:^0.6.0" "@rollup/plugin-commonjs": "npm:^26.0.0" "@rollup/plugin-json": "npm:^6.0.0" "@rollup/plugin-node-resolve": "npm:^15.0.0" @@ -2851,37 +2855,46 @@ __metadata: "@types/npm-packlist": "npm:^3.0.0" "@types/shell-quote": "npm:^1.7.5" bfj: "npm:^9.0.2" + buffer: "npm:^6.0.3" chalk: "npm:^4.0.0" - chokidar: "npm:^3.5.3" + chokidar: "npm:^3.3.1" cleye: "npm:^2.3.0" - cross-spawn: "npm:^7.0.6" + cross-spawn: "npm:^7.0.3" + css-loader: "npm:^6.5.1" ctrlc-windows: "npm:^2.1.0" - esbuild-loader: "npm:^4.4.2" + esbuild-loader: "npm:^4.0.0" eslint-rspack-plugin: "npm:^4.2.1" eslint-webpack-plugin: "npm:^4.2.0" - fork-ts-checker-webpack-plugin: "npm:^9.1.0" + fork-ts-checker-webpack-plugin: "npm:^9.0.0" fs-extra: "npm:^11.2.0" glob: "npm:^7.1.7" html-webpack-plugin: "npm:^5.6.3" lodash: "npm:^4.17.21" - mini-css-extract-plugin: "npm:^2.10.1" + mini-css-extract-plugin: "npm:^2.4.2" node-stdlib-browser: "npm:^1.3.1" npm-packlist: "npm:^5.0.0" p-queue: "npm:^6.6.2" postcss: "npm:^8.1.0" postcss-import: "npm:^16.1.0" + process: "npm:^0.11.10" + raw-loader: "npm:^4.0.2" react-dev-utils: "npm:^12.0.0-next.60" + react-refresh: "npm:^0.18.0" rollup: "npm:^4.27.3" rollup-plugin-dts: "npm:^6.1.0" rollup-plugin-esbuild: "npm:^6.1.1" rollup-plugin-postcss: "npm:^4.0.0" rollup-pluginutils: "npm:^2.8.2" shell-quote: "npm:^1.8.1" + style-loader: "npm:^3.3.1" + swc-loader: "npm:^0.2.3" tar: "npm:^7.5.6" ts-checker-rspack-plugin: "npm:^1.1.5" ts-morph: "npm:^24.0.0" - webpack: "npm:^5.105.4" - webpack-dev-server: "npm:^5.2.3" + util: "npm:^0.12.3" + webpack: "npm:~5.105.0" + webpack-dev-server: "npm:^5.0.0" + yml-loader: "npm:^2.1.0" yn: "npm:^4.0.0" bin: cli-module-build: bin/cli-module-build @@ -2960,8 +2973,9 @@ __metadata: chalk: "npm:^4.0.0" cleye: "npm:^2.3.0" eslint: "npm:^8.6.0" + eslint-formatter-friendly: "npm:^7.0.0" fs-extra: "npm:^11.2.0" - globby: "npm:^11.0.0" + globby: "npm:^11.1.0" shell-quote: "npm:^1.8.1" bin: cli-module-lint: bin/cli-module-lint @@ -3024,9 +3038,9 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/test-utils": "workspace:^" "@types/fs-extra": "npm:^11.0.0" - "@types/inquirer": "npm:^8" + "@types/inquirer": "npm:^8.1.3" "@types/lodash": "npm:^4.14.151" - "@types/recursive-readdir": "npm:^2.2.4" + "@types/recursive-readdir": "npm:^2.2.0" chalk: "npm:^4.0.0" cleye: "npm:^2.3.0" fs-extra: "npm:^11.2.0" @@ -3052,7 +3066,7 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" cleye: "npm:^2.3.0" - yargs: "npm:^17.0.0" + yargs: "npm:^16.2.0" peerDependencies: jest-cli: ^29.0.0 || ^30.0.0 bin: @@ -3106,7 +3120,6 @@ __metadata: "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" - "@backstage/catalog-model": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/cli-module-auth": "workspace:^" "@backstage/cli-module-build": "workspace:^" @@ -3121,78 +3134,36 @@ __metadata: "@backstage/cli-module-translations": "workspace:^" "@backstage/cli-node": "workspace:^" "@backstage/config": "workspace:^" - "@backstage/config-loader": "workspace:^" "@backstage/core-app-api": "workspace:^" "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/eslint-plugin": "workspace:^" - "@backstage/integration": "workspace:^" - "@backstage/module-federation-common": "workspace:^" "@backstage/plugin-auth-backend": "workspace:^" "@backstage/plugin-auth-backend-module-guest-provider": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" "@backstage/plugin-scaffolder-node-test-utils": "workspace:^" - "@backstage/release-manifests": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@backstage/types": "workspace:^" "@jest/environment-jsdom-abstract": "npm:^30.0.0" "@manypkg/get-packages": "npm:^1.1.3" - "@module-federation/enhanced": "npm:^0.21.6" - "@octokit/request": "npm:^8.0.0" - "@pmmmwh/react-refresh-webpack-plugin": "npm:^0.6.0" - "@rollup/plugin-commonjs": "npm:^26.0.0" - "@rollup/plugin-json": "npm:^6.0.0" - "@rollup/plugin-node-resolve": "npm:^15.0.0" - "@rollup/plugin-yaml": "npm:^4.0.0" - "@rspack/core": "npm:^1.4.11" - "@rspack/dev-server": "npm:^1.1.4" - "@rspack/plugin-react-refresh": "npm:^1.4.3" "@spotify/eslint-config-base": "npm:^15.0.0" "@spotify/eslint-config-react": "npm:^15.0.0" "@spotify/eslint-config-typescript": "npm:^15.0.0" "@swc/core": "npm:^1.15.6" - "@swc/helpers": "npm:^0.5.17" "@swc/jest": "npm:^0.2.39" - "@types/cross-spawn": "npm:^6.0.2" - "@types/ejs": "npm:^3.1.3" - "@types/express": "npm:^4.17.6" "@types/fs-extra": "npm:^11.0.0" - "@types/http-proxy": "npm:^1.17.4" - "@types/inquirer": "npm:^8.1.3" "@types/jest": "npm:^30.0.0" "@types/node": "npm:^22.13.14" - "@types/npm-packlist": "npm:^3.0.0" - "@types/proper-lockfile": "npm:^4" - "@types/recursive-readdir": "npm:^2.2.0" - "@types/rollup-plugin-peer-deps-external": "npm:^2.2.0" - "@types/rollup-plugin-postcss": "npm:^3.1.4" - "@types/shell-quote": "npm:^1.7.5" - "@types/svgo": "npm:^2.6.2" - "@types/terser-webpack-plugin": "npm:^5.0.4" - "@types/webpack-env": "npm:^1.15.2" - "@types/webpack-sources": "npm:^3.2.3" "@typescript-eslint/eslint-plugin": "npm:^8.17.0" "@typescript-eslint/parser": "npm:^8.16.0" - bfj: "npm:^9.0.2" - buffer: "npm:^6.0.3" chalk: "npm:^4.0.0" - chokidar: "npm:^3.3.1" - cleye: "npm:^2.3.0" commander: "npm:^14.0.3" cross-fetch: "npm:^4.0.0" - cross-spawn: "npm:^7.0.3" - css-loader: "npm:^6.5.1" - ctrlc-windows: "npm:^2.1.0" - del: "npm:^8.0.0" - esbuild: "npm:^0.27.0" - esbuild-loader: "npm:^4.0.0" eslint: "npm:^8.6.0" eslint-config-prettier: "npm:^9.0.0" - eslint-formatter-friendly: "npm:^7.0.0" eslint-plugin-deprecation: "npm:^3.0.0" eslint-plugin-import: "npm:^2.31.0" eslint-plugin-jest: "npm:^28.9.0" @@ -3200,108 +3171,28 @@ __metadata: eslint-plugin-react: "npm:^7.37.2" eslint-plugin-react-hooks: "npm:^5.0.0" eslint-plugin-unused-imports: "npm:^4.1.4" - eslint-rspack-plugin: "npm:^4.2.1" - eslint-webpack-plugin: "npm:^4.2.0" - express: "npm:^4.22.0" - fork-ts-checker-webpack-plugin: "npm:^9.0.0" fs-extra: "npm:^11.2.0" - git-url-parse: "npm:^15.0.0" glob: "npm:^7.1.7" - global-agent: "npm:^3.0.0" - globby: "npm:^11.1.0" - handlebars: "npm:^4.7.3" - html-webpack-plugin: "npm:^5.6.3" - inquirer: "npm:^8.2.0" jest: "npm:^30.2.0" jest-css-modules: "npm:^2.1.0" jsdom: "npm:^27.1.0" - json-schema: "npm:^0.4.0" - keytar: "npm:^7.9.0" - lodash: "npm:^4.17.21" - mini-css-extract-plugin: "npm:^2.4.2" - minimatch: "npm:^10.2.1" - msw: "npm:^1.0.0" - node-stdlib-browser: "npm:^1.3.1" nodemon: "npm:^3.0.1" - npm-packlist: "npm:^5.0.0" - ora: "npm:^5.3.0" - p-queue: "npm:^6.6.2" pirates: "npm:^4.0.6" postcss: "npm:^8.1.0" - postcss-import: "npm:^16.1.0" - process: "npm:^0.11.10" - proper-lockfile: "npm:^4.1.2" - raw-loader: "npm:^4.0.2" - react-dev-utils: "npm:^12.0.0-next.60" - react-refresh: "npm:^0.18.0" - recursive-readdir: "npm:^2.2.2" - replace-in-file: "npm:^7.1.0" - rollup: "npm:^4.27.3" - rollup-plugin-dts: "npm:^6.1.0" - rollup-plugin-esbuild: "npm:^6.1.1" - rollup-plugin-postcss: "npm:^4.0.0" - rollup-pluginutils: "npm:^2.8.2" - semver: "npm:^7.5.3" - shell-quote: "npm:^1.8.1" - style-loader: "npm:^3.3.1" sucrase: "npm:^3.20.2" - swc-loader: "npm:^0.2.3" - tar: "npm:^7.5.6" - terser-webpack-plugin: "npm:^5.1.3" - ts-checker-rspack-plugin: "npm:^1.1.5" - ts-morph: "npm:^24.0.0" - undici: "npm:^7.2.3" - util: "npm:^0.12.3" - webpack: "npm:~5.105.0" - webpack-dev-server: "npm:^5.0.0" yaml: "npm:^2.0.0" - yargs: "npm:^16.2.0" - yml-loader: "npm:^2.1.0" - yn: "npm:^4.0.0" - zod: "npm:^3.25.76" - zod-validation-error: "npm:^4.0.2" peerDependencies: "@jest/environment-jsdom-abstract": ^30.0.0 - "@module-federation/enhanced": ^0.21.6 - "@pmmmwh/react-refresh-webpack-plugin": ^0.6.0 - esbuild-loader: ^4.0.0 - eslint-webpack-plugin: ^4.2.0 - fork-ts-checker-webpack-plugin: ^9.0.0 jest: ^29.0.0 || ^30.0.0 jest-environment-jsdom: "*" jsdom: ^27.1.0 - mini-css-extract-plugin: ^2.4.2 - terser-webpack-plugin: ^5.1.3 - webpack: ~5.105.0 - webpack-dev-server: ^5.0.0 - dependenciesMeta: - keytar: - optional: true peerDependenciesMeta: "@jest/environment-jsdom-abstract": optional: true - "@module-federation/enhanced": - optional: true - "@pmmmwh/react-refresh-webpack-plugin": - optional: true - esbuild-loader: - optional: true - eslint-webpack-plugin: - optional: true - fork-ts-checker-webpack-plugin: - optional: true jest-environment-jsdom: optional: true jsdom: optional: true - mini-css-extract-plugin: - optional: true - terser-webpack-plugin: - optional: true - webpack: - optional: true - webpack-dev-server: - optional: true bin: backstage-cli: bin/backstage-cli languageName: unknown @@ -14946,7 +14837,7 @@ __metadata: languageName: node linkType: hard -"@pmmmwh/react-refresh-webpack-plugin@npm:^0.6.0, @pmmmwh/react-refresh-webpack-plugin@npm:^0.6.2": +"@pmmmwh/react-refresh-webpack-plugin@npm:^0.6.0": version: 0.6.2 resolution: "@pmmmwh/react-refresh-webpack-plugin@npm:0.6.2" dependencies: @@ -18333,13 +18224,6 @@ __metadata: languageName: node linkType: hard -"@sindresorhus/merge-streams@npm:^2.1.0": - version: 2.3.0 - resolution: "@sindresorhus/merge-streams@npm:2.3.0" - checksum: 10/798bcb53cd1ace9df84fcdd1ba86afdc9e0cd84f5758d26ae9b1eefd8e8887e5fc30051132b9e74daf01bb41fa5a2faf1369361f83d76a3b3d7ee938058fd71c - languageName: node - linkType: hard - "@sinonjs/commons@npm:^2.0.0": version: 2.0.0 resolution: "@sinonjs/commons@npm:2.0.0" @@ -20636,7 +20520,7 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:^0.5.0, @swc/helpers@npm:^0.5.17, @swc/helpers@npm:^0.5.8": +"@swc/helpers@npm:^0.5.0, @swc/helpers@npm:^0.5.8": version: 0.5.19 resolution: "@swc/helpers@npm:0.5.19" dependencies: @@ -21440,13 +21324,6 @@ __metadata: languageName: node linkType: hard -"@types/ejs@npm:^3.1.3": - version: 3.1.5 - resolution: "@types/ejs@npm:3.1.5" - checksum: 10/918898fd279108087722c1713e2ddb0c152ab839397946d164db8a18b5bbd732af9746373882a9bcf4843d35c6b191a8f569a7a4e51e90726d24501b39f40367 - languageName: node - linkType: hard - "@types/emscripten@npm:^1.39.6": version: 1.39.10 resolution: "@types/emscripten@npm:1.39.10" @@ -21680,7 +21557,7 @@ __metadata: languageName: node linkType: hard -"@types/inquirer@npm:^8, @types/inquirer@npm:^8.1.3": +"@types/inquirer@npm:^8.1.3": version: 8.2.12 resolution: "@types/inquirer@npm:8.2.12" dependencies: @@ -22454,7 +22331,7 @@ __metadata: languageName: node linkType: hard -"@types/recursive-readdir@npm:^2.2.0, @types/recursive-readdir@npm:^2.2.4": +"@types/recursive-readdir@npm:^2.2.0": version: 2.2.4 resolution: "@types/recursive-readdir@npm:2.2.4" dependencies: @@ -22519,24 +22396,6 @@ __metadata: languageName: node linkType: hard -"@types/rollup-plugin-peer-deps-external@npm:^2.2.0": - version: 2.2.6 - resolution: "@types/rollup-plugin-peer-deps-external@npm:2.2.6" - peerDependencies: - rollup: "*" - checksum: 10/9fcee30d60d9d8de0f4bbf7694c254a18798b0ff415563a60fb2ed8c6c46423c64e1a977e0344b8393c26221dbd6e74d9e872c2694b518fcf149ba85d94e7eac - languageName: node - linkType: hard - -"@types/rollup-plugin-postcss@npm:^3.1.4": - version: 3.1.4 - resolution: "@types/rollup-plugin-postcss@npm:3.1.4" - dependencies: - rollup-plugin-postcss: "npm:*" - checksum: 10/a94119c43db77ad10a96f34a4190b678e87fe63bdedfb2b989b64a9c0e15680c034d728daa4ade9cfd31d2fdc48827c79ff69ad2599d0b323c2c321896866cf5 - languageName: node - linkType: hard - "@types/sarif@npm:^2.1.4": version: 2.1.5 resolution: "@types/sarif@npm:2.1.5" @@ -22638,13 +22497,6 @@ __metadata: languageName: node linkType: hard -"@types/source-list-map@npm:*": - version: 0.1.6 - resolution: "@types/source-list-map@npm:0.1.6" - checksum: 10/9cd294c121f1562062de5d241fe4d10780b1131b01c57434845fe50968e9dcf67ede444591c2b1ad6d3f9b6bc646ac02cc8f51a3577c795f9c64cf4573dcc6b1 - languageName: node - linkType: hard - "@types/ssh2-streams@npm:*": version: 0.1.8 resolution: "@types/ssh2-streams@npm:0.1.8" @@ -22715,15 +22567,6 @@ __metadata: languageName: node linkType: hard -"@types/svgo@npm:^2.6.2": - version: 2.6.4 - resolution: "@types/svgo@npm:2.6.4" - dependencies: - "@types/node": "npm:*" - checksum: 10/9632b350949677fa68d6f13b4d45495a4af3108bb5f020a7257ae5a883e20b9efc0fada3bc3e012f215be312fabe5a28485fffaff5afd6da4daa8cb4fe5b04a2 - languageName: node - linkType: hard - "@types/swagger-ui-react@npm:^5.0.0": version: 5.18.0 resolution: "@types/swagger-ui-react@npm:5.18.0" @@ -22751,15 +22594,6 @@ __metadata: languageName: node linkType: hard -"@types/terser-webpack-plugin@npm:^5.0.4": - version: 5.2.0 - resolution: "@types/terser-webpack-plugin@npm:5.2.0" - dependencies: - terser-webpack-plugin: "npm:*" - checksum: 10/475b0f160c9f83641255f6516b69d7908b9e3e8e8ab653f3a257690249f9614f9386c0897eba6e4e35182ec0d83f57454d62fb94b38ae7c171891641350072ee - languageName: node - linkType: hard - "@types/through@npm:*": version: 0.0.30 resolution: "@types/through@npm:0.0.30" @@ -22835,24 +22669,13 @@ __metadata: languageName: node linkType: hard -"@types/webpack-env@npm:^1.15.2, @types/webpack-env@npm:^1.15.3": +"@types/webpack-env@npm:^1.15.3": version: 1.18.8 resolution: "@types/webpack-env@npm:1.18.8" checksum: 10/f3932f3d6c2530f644cfc898eda1ab8182d6ae57f555c2f0179d813549b639078671b71e4041831fc306c5ebe61f5cdac794fe4ceae281fce8bf67e23661a488 languageName: node linkType: hard -"@types/webpack-sources@npm:^3.2.3": - version: 3.2.3 - resolution: "@types/webpack-sources@npm:3.2.3" - dependencies: - "@types/node": "npm:*" - "@types/source-list-map": "npm:*" - source-map: "npm:^0.7.3" - checksum: 10/7b557f242efaa10e4e3e18cc4171a0c98e22898570caefdd4f7b076fe8534b5abfac92c953c6604658dcb7218507f970230352511840fe9fdea31a9af3b9a906 - languageName: node - linkType: hard - "@types/webpack@npm:^5.28.0": version: 5.28.5 resolution: "@types/webpack@npm:5.28.5" @@ -29040,21 +28863,6 @@ __metadata: languageName: node linkType: hard -"del@npm:^8.0.0": - version: 8.0.1 - resolution: "del@npm:8.0.1" - dependencies: - globby: "npm:^14.0.2" - is-glob: "npm:^4.0.3" - is-path-cwd: "npm:^3.0.0" - is-path-inside: "npm:^4.0.0" - p-map: "npm:^7.0.2" - presentable-error: "npm:^0.0.1" - slash: "npm:^5.1.0" - checksum: 10/53ed4a379a68c90e7d6d3bcce09c49229e77de9a946d0a5fc25f45b16c950cb8665986b7d0d0423416c03bfd43e0f31e528c5a19c558fe47449be9d6fae7f846 - languageName: node - linkType: hard - "delayed-stream@npm:~1.0.0": version: 1.0.0 resolution: "delayed-stream@npm:1.0.0" @@ -30243,7 +30051,7 @@ __metadata: languageName: node linkType: hard -"esbuild-loader@npm:^4.0.0, esbuild-loader@npm:^4.4.2": +"esbuild-loader@npm:^4.0.0": version: 4.4.2 resolution: "esbuild-loader@npm:4.4.2" dependencies: @@ -32075,7 +31883,7 @@ __metadata: languageName: node linkType: hard -"fork-ts-checker-webpack-plugin@npm:^9.0.0, fork-ts-checker-webpack-plugin@npm:^9.1.0": +"fork-ts-checker-webpack-plugin@npm:^9.0.0": version: 9.1.0 resolution: "fork-ts-checker-webpack-plugin@npm:9.1.0" dependencies: @@ -33003,20 +32811,6 @@ __metadata: languageName: node linkType: hard -"globby@npm:^14.0.2": - version: 14.0.2 - resolution: "globby@npm:14.0.2" - dependencies: - "@sindresorhus/merge-streams": "npm:^2.1.0" - fast-glob: "npm:^3.3.2" - ignore: "npm:^5.2.4" - path-type: "npm:^5.0.0" - slash: "npm:^5.1.0" - unicorn-magic: "npm:^0.1.0" - checksum: 10/67660da70fc1223f7170c1a62ba6c373385e9e39765d952b6518606dec15ed8c7958e9dae6ba5752a31dbc1e9126f146938b830ad680fe794141734ffc3fbb75 - languageName: node - linkType: hard - "globrex@npm:^0.1.2": version: 0.1.2 resolution: "globrex@npm:0.1.2" @@ -34278,7 +34072,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.1.4, ignore@npm:^5.2.0, ignore@npm:^5.2.4": +"ignore@npm:^5.1.4, ignore@npm:^5.2.0": version: 5.3.2 resolution: "ignore@npm:5.3.2" checksum: 10/cceb6a457000f8f6a50e1196429750d782afce5680dd878aa4221bd79972d68b3a55b4b1458fc682be978f4d3c6a249046aa0880637367216444ab7b014cfc98 @@ -35087,13 +34881,6 @@ __metadata: languageName: node linkType: hard -"is-path-cwd@npm:^3.0.0": - version: 3.0.0 - resolution: "is-path-cwd@npm:3.0.0" - checksum: 10/bc34d13b6a03dfca4a3ab6a8a5ba78ae4b24f4f1db4b2b031d2760c60d0913bd16a4b980dcb4e590adfc906649d5f5132684079a3972bd219da49deebb9adea8 - languageName: node - linkType: hard - "is-path-inside@npm:^3.0.2, is-path-inside@npm:^3.0.3": version: 3.0.3 resolution: "is-path-inside@npm:3.0.3" @@ -35101,13 +34888,6 @@ __metadata: languageName: node linkType: hard -"is-path-inside@npm:^4.0.0": - version: 4.0.0 - resolution: "is-path-inside@npm:4.0.0" - checksum: 10/8810fa11c58e6360b82c3e0d6cd7d9c7d0392d3ac9eb10f980b81f9839f40ac6d1d6d6f05d069db0d227759801228f0b072e1b6c343e4469b065ab5fe0b68fe5 - languageName: node - linkType: hard - "is-plain-obj@npm:^3.0.0": version: 3.0.0 resolution: "is-plain-obj@npm:3.0.0" @@ -39113,7 +38893,7 @@ __metadata: languageName: node linkType: hard -"mini-css-extract-plugin@npm:^2.10.1, mini-css-extract-plugin@npm:^2.4.2": +"mini-css-extract-plugin@npm:^2.4.2": version: 2.10.1 resolution: "mini-css-extract-plugin@npm:2.10.1" dependencies: @@ -41860,13 +41640,6 @@ __metadata: languageName: node linkType: hard -"path-type@npm:^5.0.0": - version: 5.0.0 - resolution: "path-type@npm:5.0.0" - checksum: 10/15ec24050e8932c2c98d085b72cfa0d6b4eeb4cbde151a0a05726d8afae85784fc5544f733d8dfc68536587d5143d29c0bd793623fad03d7e61cc00067291cd5 - languageName: node - linkType: hard - "pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" @@ -42892,13 +42665,6 @@ __metadata: languageName: node linkType: hard -"presentable-error@npm:^0.0.1": - version: 0.0.1 - resolution: "presentable-error@npm:0.0.1" - checksum: 10/013809ee7a47ced847a8d860e9b89a56cdd8c4f1ad04ad8da1e58fd60843f77f497d204146bb15aaa9793d3b94ad8626eed01256fc9eb5839a545af2000a5fa4 - languageName: node - linkType: hard - "prettier@npm:^2.2.1, prettier@npm:^2.7.1": version: 2.8.8 resolution: "prettier@npm:2.8.8" @@ -45423,7 +45189,7 @@ __metadata: languageName: node linkType: hard -"rollup-plugin-postcss@npm:*, rollup-plugin-postcss@npm:^4.0.0": +"rollup-plugin-postcss@npm:^4.0.0": version: 4.0.2 resolution: "rollup-plugin-postcss@npm:4.0.2" dependencies: @@ -46534,13 +46300,6 @@ __metadata: languageName: node linkType: hard -"slash@npm:^5.1.0": - version: 5.1.0 - resolution: "slash@npm:5.1.0" - checksum: 10/2c41ec6fb1414cd9bba0fa6b1dd00e8be739e3fe85d079c69d4b09ca5f2f86eafd18d9ce611c0c0f686428638a36c272a6ac14799146a8295f259c10cc45cde4 - languageName: node - linkType: hard - "slice-ansi@npm:^3.0.0": version: 3.0.0 resolution: "slice-ansi@npm:3.0.0" @@ -48139,7 +47898,7 @@ __metadata: languageName: node linkType: hard -"terser-webpack-plugin@npm:*, terser-webpack-plugin@npm:^5.1.3, terser-webpack-plugin@npm:^5.3.17": +"terser-webpack-plugin@npm:^5.3.17": version: 5.3.17 resolution: "terser-webpack-plugin@npm:5.3.17" dependencies: @@ -49405,13 +49164,6 @@ __metadata: languageName: node linkType: hard -"unicorn-magic@npm:^0.1.0": - version: 0.1.0 - resolution: "unicorn-magic@npm:0.1.0" - checksum: 10/9b4d0e9809807823dc91d0920a4a4c0cff2de3ebc54ee87ac1ee9bc75eafd609b09d1f14495e0173aef26e01118706196b6ab06a75fe0841028b3983a8af313f - languageName: node - linkType: hard - "unified@npm:^10.0.0": version: 10.1.0 resolution: "unified@npm:10.1.0" @@ -50489,7 +50241,7 @@ __metadata: languageName: node linkType: hard -"webpack-dev-server@npm:^5.0.0, webpack-dev-server@npm:^5.2.3": +"webpack-dev-server@npm:^5.0.0": version: 5.2.3 resolution: "webpack-dev-server@npm:5.2.3" dependencies: @@ -50558,7 +50310,7 @@ __metadata: languageName: node linkType: hard -"webpack@npm:^5, webpack@npm:^5.105.4, webpack@npm:~5.105.0": +"webpack@npm:^5, webpack@npm:~5.105.0": version: 5.105.4 resolution: "webpack@npm:5.105.4" dependencies: @@ -51114,7 +50866,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.1.1, yargs@npm:^17.3.1, yargs@npm:^17.7.1, yargs@npm:^17.7.2": +"yargs@npm:17.7.2, yargs@npm:^17.1.1, yargs@npm:^17.3.1, yargs@npm:^17.7.1, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: From 47b50ef3c46566e1f5f4f9cfa32be47dc2fa500c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 12:56:32 +0100 Subject: [PATCH 30/45] Add back @types/webpack-env to CLI dependencies The CLI provides tsconfig presets that include webpack-env in the types array, so @types/webpack-env must remain a dependency of the CLI package for consuming apps to compile correctly. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli/package.json | 1 + yarn.lock | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 059737a6f3..2158b2b85e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -68,6 +68,7 @@ "@spotify/eslint-config-typescript": "^15.0.0", "@swc/core": "^1.15.6", "@swc/jest": "^0.2.39", + "@types/webpack-env": "^1.15.2", "@typescript-eslint/eslint-plugin": "^8.17.0", "@typescript-eslint/parser": "^8.16.0", "chalk": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index d470627b63..7b20688f16 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3157,6 +3157,7 @@ __metadata: "@types/fs-extra": "npm:^11.0.0" "@types/jest": "npm:^30.0.0" "@types/node": "npm:^22.13.14" + "@types/webpack-env": "npm:^1.15.2" "@typescript-eslint/eslint-plugin": "npm:^8.17.0" "@typescript-eslint/parser": "npm:^8.16.0" chalk: "npm:^4.0.0" @@ -22669,7 +22670,7 @@ __metadata: languageName: node linkType: hard -"@types/webpack-env@npm:^1.15.3": +"@types/webpack-env@npm:^1.15.2, @types/webpack-env@npm:^1.15.3": version: 1.18.8 resolution: "@types/webpack-env@npm:1.18.8" checksum: 10/f3932f3d6c2530f644cfc898eda1ab8182d6ae57f555c2f0179d813549b639078671b71e4041831fc306c5ebe61f5cdac794fe4ceae281fce8bf67e23661a488 From 7db7ca5714ca477f96eed7c5d6d1746dcab76632 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 13:35:12 +0100 Subject: [PATCH 31/45] Convert discovered module paths to file URLs for Windows compatibility On Windows, require.resolve() returns paths like D:\...\index.cjs.js which when passed to import() causes ERR_UNSUPPORTED_ESM_URL_SCHEME because the D: prefix is interpreted as a URL protocol. Use pathToFileURL() to produce proper file:// URLs. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli/src/wiring/discoverCliModules.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/wiring/discoverCliModules.ts b/packages/cli/src/wiring/discoverCliModules.ts index fb5e8c7469..e2945d2631 100644 --- a/packages/cli/src/wiring/discoverCliModules.ts +++ b/packages/cli/src/wiring/discoverCliModules.ts @@ -18,6 +18,7 @@ import { targetPaths } from '@backstage/cli-common'; import { PackageRoles } from '@backstage/cli-node'; import fs from 'node:fs'; import { resolve as resolvePath } from 'node:path'; +import { pathToFileURL } from 'node:url'; /** * Scans the target project root's package.json for dependencies that are CLI @@ -57,7 +58,7 @@ export function discoverCliModules(): string[] { const depPkg = JSON.parse(fs.readFileSync(depPkgPath, 'utf8')); if (PackageRoles.getRoleFromPackage(depPkg) === 'cli-module') { const resolvedPath = require.resolve(depName, { paths: [rootDir] }); - modules.push(resolvedPath); + modules.push(pathToFileURL(resolvedPath).href); } } catch { // Skip packages that can't be resolved or read From 7781ae5911c56355b230461edcbd11cc26780948 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 15:01:35 +0100 Subject: [PATCH 32/45] Add @backstage/cli-defaults package Introduces a new `@backstage/cli-defaults` package that re-exports all standard CLI modules as a single array, simplifying dependency management for consumers. The CLI's `CliInitializer` is updated to support array exports alongside single module exports. The create-app template, changesets, and CLI fallback are updated to use `@backstage/cli-defaults` instead of listing 11 individual modules. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/cli-defaults-introduce.md | 5 ++ .changeset/cli-discover-modules.md | 24 +++++++--- .changeset/create-app-cli-modules.md | 2 +- packages/cli-defaults/.eslintrc.js | 1 + packages/cli-defaults/catalog-info.yaml | 10 ++++ packages/cli-defaults/package.json | 48 +++++++++++++++++++ packages/cli-defaults/src/index.ts | 40 ++++++++++++++++ packages/cli/package.json | 12 +---- packages/cli/src/index.ts | 17 ++----- packages/cli/src/wiring/CliInitializer.ts | 28 ++++++++--- packages/create-app/src/lib/tasks.test.ts | 1 + packages/create-app/src/lib/versions.ts | 2 + .../templates/default-app/package.json.hbs | 12 +---- yarn.lock | 31 +++++++----- 14 files changed, 172 insertions(+), 61 deletions(-) create mode 100644 .changeset/cli-defaults-introduce.md create mode 100644 packages/cli-defaults/.eslintrc.js create mode 100644 packages/cli-defaults/catalog-info.yaml create mode 100644 packages/cli-defaults/package.json create mode 100644 packages/cli-defaults/src/index.ts diff --git a/.changeset/cli-defaults-introduce.md b/.changeset/cli-defaults-introduce.md new file mode 100644 index 0000000000..b6bb175e62 --- /dev/null +++ b/.changeset/cli-defaults-introduce.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli-defaults': minor +--- + +Introduced `@backstage/cli-defaults`, a convenience package that bundles all standard Backstage CLI modules. Install this single package as a `devDependency` to get the full default set of CLI commands without listing each module individually. diff --git a/.changeset/cli-discover-modules.md b/.changeset/cli-discover-modules.md index 428a6eb883..751facdf1d 100644 --- a/.changeset/cli-discover-modules.md +++ b/.changeset/cli-discover-modules.md @@ -4,7 +4,23 @@ The CLI now automatically discovers CLI modules from the project root's `dependencies` and `devDependencies`. Any installed package with the `cli-module` Backstage role will be loaded automatically without needing to be hardcoded in the CLI itself. -If no CLI modules are found in the project dependencies, the CLI falls back to the built-in set of modules and prints a deprecation warning. This fallback will be removed in a future release. To prepare for this, add the following CLI modules as `devDependencies` in your root `package.json`: +If no CLI modules are found in the project dependencies, the CLI falls back to the built-in set of modules and prints a deprecation warning. This fallback will be removed in a future release. To prepare for this, add `@backstage/cli-defaults` as a `devDependency` in your root `package.json`: + +```json +{ + "devDependencies": { + "@backstage/cli-defaults": "backstage:^" + } +} +``` + +If you are not using the Backstage Yarn plugin, run the following instead: + +```sh +yarn workspace root add --dev @backstage/cli-defaults +``` + +For fine-grained control you can instead install individual CLI modules: ```json { @@ -23,9 +39,3 @@ If no CLI modules are found in the project dependencies, the CLI falls back to t } } ``` - -If you are not using the Backstage Yarn plugin, run the following instead: - -```sh -yarn workspace root add --dev @backstage/cli-module-auth @backstage/cli-module-build @backstage/cli-module-config @backstage/cli-module-create-github-app @backstage/cli-module-info @backstage/cli-module-lint @backstage/cli-module-maintenance @backstage/cli-module-migrate @backstage/cli-module-new @backstage/cli-module-test-jest @backstage/cli-module-translations -``` diff --git a/.changeset/create-app-cli-modules.md b/.changeset/create-app-cli-modules.md index 4e01b65260..c1a8ca9a26 100644 --- a/.changeset/create-app-cli-modules.md +++ b/.changeset/create-app-cli-modules.md @@ -2,4 +2,4 @@ '@backstage/create-app': patch --- -The create-app templates now include all standard `@backstage/cli-module-*` packages as `devDependencies`, enabling the CLI's automatic module discovery for newly created projects. +The create-app templates now include `@backstage/cli-defaults` as a `devDependency`, enabling the CLI's automatic module discovery for newly created projects. diff --git a/packages/cli-defaults/.eslintrc.js b/packages/cli-defaults/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/cli-defaults/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/cli-defaults/catalog-info.yaml b/packages/cli-defaults/catalog-info.yaml new file mode 100644 index 0000000000..3cac883c36 --- /dev/null +++ b/packages/cli-defaults/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-cli-defaults + title: '@backstage/cli-defaults' + description: Default set of CLI modules for the Backstage CLI +spec: + lifecycle: experimental + type: backstage-cli-module + owner: tooling-maintainers diff --git a/packages/cli-defaults/package.json b/packages/cli-defaults/package.json new file mode 100644 index 0000000000..587e54cfe9 --- /dev/null +++ b/packages/cli-defaults/package.json @@ -0,0 +1,48 @@ +{ + "name": "@backstage/cli-defaults", + "version": "0.0.0", + "description": "Default set of CLI modules for the Backstage CLI", + "backstage": { + "role": "cli-module" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/cli-defaults" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/cli-module-auth": "workspace:^", + "@backstage/cli-module-build": "workspace:^", + "@backstage/cli-module-config": "workspace:^", + "@backstage/cli-module-create-github-app": "workspace:^", + "@backstage/cli-module-info": "workspace:^", + "@backstage/cli-module-lint": "workspace:^", + "@backstage/cli-module-maintenance": "workspace:^", + "@backstage/cli-module-migrate": "workspace:^", + "@backstage/cli-module-new": "workspace:^", + "@backstage/cli-module-test-jest": "workspace:^", + "@backstage/cli-module-translations": "workspace:^" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } +} diff --git a/packages/cli-defaults/src/index.ts b/packages/cli-defaults/src/index.ts new file mode 100644 index 0000000000..95c9052b1d --- /dev/null +++ b/packages/cli-defaults/src/index.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2025 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 auth from '@backstage/cli-module-auth'; +import build from '@backstage/cli-module-build'; +import config from '@backstage/cli-module-config'; +import createGithubApp from '@backstage/cli-module-create-github-app'; +import info from '@backstage/cli-module-info'; +import lint from '@backstage/cli-module-lint'; +import maintenance from '@backstage/cli-module-maintenance'; +import migrate from '@backstage/cli-module-migrate'; +import newModule from '@backstage/cli-module-new'; +import testJest from '@backstage/cli-module-test-jest'; +import translations from '@backstage/cli-module-translations'; + +export default [ + auth, + build, + config, + createGithubApp, + info, + lint, + maintenance, + migrate, + newModule, + testJest, + translations, +]; diff --git a/packages/cli/package.json b/packages/cli/package.json index 2158b2b85e..600f150654 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -48,17 +48,7 @@ }, "dependencies": { "@backstage/cli-common": "workspace:^", - "@backstage/cli-module-auth": "workspace:^", - "@backstage/cli-module-build": "workspace:^", - "@backstage/cli-module-config": "workspace:^", - "@backstage/cli-module-create-github-app": "workspace:^", - "@backstage/cli-module-info": "workspace:^", - "@backstage/cli-module-lint": "workspace:^", - "@backstage/cli-module-maintenance": "workspace:^", - "@backstage/cli-module-migrate": "workspace:^", - "@backstage/cli-module-new": "workspace:^", - "@backstage/cli-module-test-jest": "workspace:^", - "@backstage/cli-module-translations": "workspace:^", + "@backstage/cli-defaults": "workspace:^", "@backstage/cli-node": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/eslint-plugin": "workspace:^", diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index f5056f8ba3..483717fc64 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -35,22 +35,13 @@ import { discoverCliModules } from './wiring/discoverCliModules'; `No CLI modules found in the project root dependencies. ` + `Falling back to the built-in set of modules.\n` + `This fallback will be removed in a future release. ` + - `Please add the CLI modules you need as devDependencies ` + - `in your root package.json.\n`, + `Please add @backstage/cli-defaults as a devDependency ` + + `in your root package.json, or install individual ` + + `@backstage/cli-module-* packages for fine-grained control.\n`, ), ); - initializer.add(import('@backstage/cli-module-build')); - initializer.add(import('@backstage/cli-module-config')); - initializer.add(import('@backstage/cli-module-create-github-app')); - initializer.add(import('@backstage/cli-module-info')); - initializer.add(import('@backstage/cli-module-lint')); - initializer.add(import('@backstage/cli-module-maintenance')); - initializer.add(import('@backstage/cli-module-migrate')); - initializer.add(import('@backstage/cli-module-new')); - initializer.add(import('@backstage/cli-module-test-jest')); - initializer.add(import('@backstage/cli-module-translations')); - initializer.add(import('@backstage/cli-module-auth')); + initializer.add(import('@backstage/cli-defaults')); } await initializer.run(); diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index a09adbbc89..4e1067d780 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -39,18 +39,23 @@ function isNodeHidden(node: CommandNode): boolean { return children.every(child => isNodeHidden(child)); } -type UninitializedFeature = CliModule | Promise<{ default: CliModule }>; +type UninitializedFeature = + | CliModule + | CliModule[] + | Promise<{ default: CliModule | CliModule[] }>; export class CliInitializer { private graph = new CommandGraph(); private commandRegistry = new CommandRegistry(this.graph); - #uninitiazedFeatures: Promise[] = []; + #uninitiazedFeatures: Promise[] = []; add(feature: UninitializedFeature) { if (isPromise(feature)) { this.#uninitiazedFeatures.push( feature.then(f => unwrapFeature(f.default)), ); + } else if (Array.isArray(feature)) { + this.#uninitiazedFeatures.push(Promise.resolve(feature)); } else { this.#uninitiazedFeatures.push(Promise.resolve(feature)); } @@ -68,9 +73,14 @@ export class CliInitializer { } async #doInit() { - const features = await Promise.all(this.#uninitiazedFeatures); - for (const feature of features) { - await this.#register(feature); + const resolved = await Promise.all(this.#uninitiazedFeatures); + for (const featureOrArray of resolved) { + const features = Array.isArray(featureOrArray) + ? featureOrArray + : [featureOrArray]; + for (const feature of features) { + await this.#register(feature); + } } } @@ -186,8 +196,12 @@ export class CliInitializer { /** @internal */ export function unwrapFeature( - feature: CliModule | { default: CliModule }, -): CliModule { + feature: CliModule | CliModule[] | { default: CliModule | CliModule[] }, +): CliModule | CliModule[] { + if (Array.isArray(feature)) { + return feature; + } + if ('$$type' in feature) { return feature; } diff --git a/packages/create-app/src/lib/tasks.test.ts b/packages/create-app/src/lib/tasks.test.ts index 0115790b81..ff2f3eb4d6 100644 --- a/packages/create-app/src/lib/tasks.test.ts +++ b/packages/create-app/src/lib/tasks.test.ts @@ -50,6 +50,7 @@ jest.mock('./versions', () => ({ packageVersions: { root: '1.2.3', '@backstage/cli': '1.0.0', + '@backstage/cli-defaults': '1.0.0', '@backstage/cli-module-auth': '1.0.0', '@backstage/cli-module-build': '1.0.0', '@backstage/cli-module-config': '1.0.0', diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index bd19366e55..e770b88f3f 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -38,6 +38,7 @@ import { version as backendDefaults } from '../../../backend-defaults/package.js import { version as catalogClient } from '../../../catalog-client/package.json'; import { version as catalogModel } from '../../../catalog-model/package.json'; import { version as cli } from '../../../cli/package.json'; +import { version as cliDefaults } from '../../../cli-defaults/package.json'; import { version as cliModuleAuth } from '../../../cli-module-auth/package.json'; import { version as cliModuleBuild } from '../../../cli-module-build/package.json'; import { version as cliModuleConfig } from '../../../cli-module-config/package.json'; @@ -118,6 +119,7 @@ export const packageVersions = { '@backstage/catalog-client': catalogClient, '@backstage/catalog-model': catalogModel, '@backstage/cli': cli, + '@backstage/cli-defaults': cliDefaults, '@backstage/cli-module-auth': cliModuleAuth, '@backstage/cli-module-build': cliModuleBuild, '@backstage/cli-module-config': cliModuleConfig, diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index ca29f02dc0..4262e0fc82 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -28,17 +28,7 @@ ], "devDependencies": { "@backstage/cli": "^{{version '@backstage/cli'}}", - "@backstage/cli-module-auth": "^{{version '@backstage/cli-module-auth'}}", - "@backstage/cli-module-build": "^{{version '@backstage/cli-module-build'}}", - "@backstage/cli-module-config": "^{{version '@backstage/cli-module-config'}}", - "@backstage/cli-module-create-github-app": "^{{version '@backstage/cli-module-create-github-app'}}", - "@backstage/cli-module-info": "^{{version '@backstage/cli-module-info'}}", - "@backstage/cli-module-lint": "^{{version '@backstage/cli-module-lint'}}", - "@backstage/cli-module-maintenance": "^{{version '@backstage/cli-module-maintenance'}}", - "@backstage/cli-module-migrate": "^{{version '@backstage/cli-module-migrate'}}", - "@backstage/cli-module-new": "^{{version '@backstage/cli-module-new'}}", - "@backstage/cli-module-test-jest": "^{{version '@backstage/cli-module-test-jest'}}", - "@backstage/cli-module-translations": "^{{version '@backstage/cli-module-translations'}}", + "@backstage/cli-defaults": "^{{version '@backstage/cli-defaults'}}", "@backstage/e2e-test-utils": "^{{version '@backstage/e2e-test-utils'}}", "@jest/environment-jsdom-abstract": "^30.0.0", "@playwright/test": "^1.32.3", diff --git a/yarn.lock b/yarn.lock index 7b20688f16..643fa1d573 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2801,6 +2801,25 @@ __metadata: languageName: unknown linkType: soft +"@backstage/cli-defaults@workspace:^, @backstage/cli-defaults@workspace:packages/cli-defaults": + version: 0.0.0-use.local + resolution: "@backstage/cli-defaults@workspace:packages/cli-defaults" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/cli-module-auth": "workspace:^" + "@backstage/cli-module-build": "workspace:^" + "@backstage/cli-module-config": "workspace:^" + "@backstage/cli-module-create-github-app": "workspace:^" + "@backstage/cli-module-info": "workspace:^" + "@backstage/cli-module-lint": "workspace:^" + "@backstage/cli-module-maintenance": "workspace:^" + "@backstage/cli-module-migrate": "workspace:^" + "@backstage/cli-module-new": "workspace:^" + "@backstage/cli-module-test-jest": "workspace:^" + "@backstage/cli-module-translations": "workspace:^" + languageName: unknown + linkType: soft + "@backstage/cli-module-auth@workspace:*, @backstage/cli-module-auth@workspace:^, @backstage/cli-module-auth@workspace:packages/cli-module-auth": version: 0.0.0-use.local resolution: "@backstage/cli-module-auth@workspace:packages/cli-module-auth" @@ -3121,17 +3140,7 @@ __metadata: "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" "@backstage/cli-common": "workspace:^" - "@backstage/cli-module-auth": "workspace:^" - "@backstage/cli-module-build": "workspace:^" - "@backstage/cli-module-config": "workspace:^" - "@backstage/cli-module-create-github-app": "workspace:^" - "@backstage/cli-module-info": "workspace:^" - "@backstage/cli-module-lint": "workspace:^" - "@backstage/cli-module-maintenance": "workspace:^" - "@backstage/cli-module-migrate": "workspace:^" - "@backstage/cli-module-new": "workspace:^" - "@backstage/cli-module-test-jest": "workspace:^" - "@backstage/cli-module-translations": "workspace:^" + "@backstage/cli-defaults": "workspace:^" "@backstage/cli-node": "workspace:^" "@backstage/config": "workspace:^" "@backstage/core-app-api": "workspace:^" From 4f2d7d555bc34ff8cd173db7344b693a34f79889 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 15:03:35 +0100 Subject: [PATCH 33/45] Add README files to CLI module packages Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-defaults/README.md | 26 +++++++++++++++++++ packages/cli-module-auth/README.md | 19 ++++++++++++++ packages/cli-module-build/README.md | 23 ++++++++++++++++ packages/cli-module-config/README.md | 18 +++++++++++++ .../cli-module-create-github-app/README.md | 14 ++++++++++ packages/cli-module-info/README.md | 14 ++++++++++ packages/cli-module-lint/README.md | 15 +++++++++++ packages/cli-module-maintenance/README.md | 15 +++++++++++ packages/cli-module-migrate/README.md | 20 ++++++++++++++ packages/cli-module-new/README.md | 14 ++++++++++ packages/cli-module-test-jest/README.md | 15 +++++++++++ packages/cli-module-translations/README.md | 15 +++++++++++ 12 files changed, 208 insertions(+) create mode 100644 packages/cli-defaults/README.md create mode 100644 packages/cli-module-auth/README.md create mode 100644 packages/cli-module-build/README.md create mode 100644 packages/cli-module-config/README.md create mode 100644 packages/cli-module-create-github-app/README.md create mode 100644 packages/cli-module-info/README.md create mode 100644 packages/cli-module-lint/README.md create mode 100644 packages/cli-module-maintenance/README.md create mode 100644 packages/cli-module-migrate/README.md create mode 100644 packages/cli-module-new/README.md create mode 100644 packages/cli-module-test-jest/README.md create mode 100644 packages/cli-module-translations/README.md diff --git a/packages/cli-defaults/README.md b/packages/cli-defaults/README.md new file mode 100644 index 0000000000..fa75c322df --- /dev/null +++ b/packages/cli-defaults/README.md @@ -0,0 +1,26 @@ +# @backstage/cli-defaults + +The default set of CLI modules for the Backstage CLI. Installing this single package provides all standard CLI commands without needing to list each module individually. + +## Included Modules + +| Module | Description | +| :--------------------------------------------------------------------------- | :--------------------------------------- | +| [`@backstage/cli-module-auth`](../cli-module-auth) | Authentication commands | +| [`@backstage/cli-module-build`](../cli-module-build) | Build, start, and packaging commands | +| [`@backstage/cli-module-config`](../cli-module-config) | Configuration inspection commands | +| [`@backstage/cli-module-create-github-app`](../cli-module-create-github-app) | GitHub App creation | +| [`@backstage/cli-module-info`](../cli-module-info) | Environment and dependency info | +| [`@backstage/cli-module-lint`](../cli-module-lint) | Linting commands | +| [`@backstage/cli-module-maintenance`](../cli-module-maintenance) | Repository maintenance commands | +| [`@backstage/cli-module-migrate`](../cli-module-migrate) | Migration and version management | +| [`@backstage/cli-module-new`](../cli-module-new) | Scaffolding for new plugins and packages | +| [`@backstage/cli-module-test-jest`](../cli-module-test-jest) | Jest-based testing commands | +| [`@backstage/cli-module-translations`](../cli-module-translations) | Translation management commands | + +For fine-grained control over which CLI commands are available, you can install individual modules instead. + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/cli-module-auth/README.md b/packages/cli-module-auth/README.md new file mode 100644 index 0000000000..2a98761ac3 --- /dev/null +++ b/packages/cli-module-auth/README.md @@ -0,0 +1,19 @@ +# @backstage/cli-module-auth + +CLI module that provides authentication commands for the Backstage CLI, enabling login, logout, and credential management for Backstage instances. + +## Commands + +| Command | Description | +| :----------------- | :------------------------------------------------------- | +| `auth login` | Log in the CLI to a Backstage instance | +| `auth logout` | Log out the CLI and clear stored credentials | +| `auth show` | Show details of an authenticated instance | +| `auth list` | List authenticated instances | +| `auth print-token` | Print an access token to stdout (auto-refresh if needed) | +| `auth select` | Select the default instance | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/cli-module-build/README.md b/packages/cli-module-build/README.md new file mode 100644 index 0000000000..355891c907 --- /dev/null +++ b/packages/cli-module-build/README.md @@ -0,0 +1,23 @@ +# @backstage/cli-module-build + +CLI module that provides build, start, and packaging commands for the Backstage CLI. + +## Commands + +| Command | Description | +| :----------------- | :------------------------------------------------------------------------ | +| `package build` | Build a package for production deployment or publishing | +| `package start` | Start a package for local development | +| `package clean` | Delete cache directories | +| `package prepack` | Prepares a package for packaging before publishing | +| `package postpack` | Restores the changes made by the prepack command | +| `repo build` | Build packages in the project, excluding bundled app and backend packages | +| `repo start` | Starts packages in the repo for local development | +| `repo clean` | Delete cache and output directories | +| `build-workspace` | Builds a temporary dist workspace from the provided packages | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) +- [Build System](https://backstage.io/docs/tooling/cli/build-system) diff --git a/packages/cli-module-config/README.md b/packages/cli-module-config/README.md new file mode 100644 index 0000000000..dc5b266d98 --- /dev/null +++ b/packages/cli-module-config/README.md @@ -0,0 +1,18 @@ +# @backstage/cli-module-config + +CLI module that provides configuration inspection commands for the Backstage CLI. + +## Commands + +| Command | Description | +| :-------------- | :------------------------------------------------------------- | +| `config docs` | Browse the configuration reference documentation | +| `config:print` | Print the app configuration for the current package | +| `config:check` | Validate that the given configuration loads and matches schema | +| `config schema` | Print the JSON schema for the given configuration | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) +- [Static Configuration](https://backstage.io/docs/conf/) diff --git a/packages/cli-module-create-github-app/README.md b/packages/cli-module-create-github-app/README.md new file mode 100644 index 0000000000..b10272ab02 --- /dev/null +++ b/packages/cli-module-create-github-app/README.md @@ -0,0 +1,14 @@ +# @backstage/cli-module-create-github-app + +CLI module that provides the `create-github-app` command for the Backstage CLI, used to create a new GitHub App in your organization for use with Backstage. + +## Commands + +| Command | Description | +| :------------------ | :----------------------------------------- | +| `create-github-app` | Create new GitHub App in your organization | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/cli-module-info/README.md b/packages/cli-module-info/README.md new file mode 100644 index 0000000000..1ba0cb3799 --- /dev/null +++ b/packages/cli-module-info/README.md @@ -0,0 +1,14 @@ +# @backstage/cli-module-info + +CLI module that provides the `info` command for the Backstage CLI, displaying environment and dependency information useful for debugging and bug reports. + +## Commands + +| Command | Description | +| :------ | :-------------------------------------------------------- | +| `info` | Show helpful information for debugging and reporting bugs | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/cli-module-lint/README.md b/packages/cli-module-lint/README.md new file mode 100644 index 0000000000..23d1f06e7e --- /dev/null +++ b/packages/cli-module-lint/README.md @@ -0,0 +1,15 @@ +# @backstage/cli-module-lint + +CLI module that provides linting commands for the Backstage CLI. + +## Commands + +| Command | Description | +| :------------- | :---------------- | +| `package lint` | Lint a package | +| `repo lint` | Lint a repository | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/cli-module-maintenance/README.md b/packages/cli-module-maintenance/README.md new file mode 100644 index 0000000000..f13e78a32e --- /dev/null +++ b/packages/cli-module-maintenance/README.md @@ -0,0 +1,15 @@ +# @backstage/cli-module-maintenance + +CLI module that provides repository maintenance commands for the Backstage CLI. + +## Commands + +| Command | Description | +| :----------------------- | :---------------------------------------- | +| `repo fix` | Automatically fix packages in the project | +| `repo list-deprecations` | List deprecations | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/cli-module-migrate/README.md b/packages/cli-module-migrate/README.md new file mode 100644 index 0000000000..842f0e645c --- /dev/null +++ b/packages/cli-module-migrate/README.md @@ -0,0 +1,20 @@ +# @backstage/cli-module-migrate + +CLI module that provides migration and version management commands for the Backstage CLI. + +## Commands + +| Command | Description | +| :----------------------------- | :---------------------------------------------------------------- | +| `versions:bump` | Bump Backstage packages to the latest versions | +| `versions:migrate` | Migrate plugins moved to the @backstage-community namespace | +| `migrate package-roles` | Add package role field to packages that don't have it | +| `migrate package-scripts` | Set package scripts according to each package role | +| `migrate package-exports` | Synchronize package subpath export definitions | +| `migrate package-lint-configs` | Migrates all packages to use @backstage/cli/config/eslint-factory | +| `migrate react-router-deps` | Migrates the react-router dependencies to be peer dependencies | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/cli-module-new/README.md b/packages/cli-module-new/README.md new file mode 100644 index 0000000000..88855e856a --- /dev/null +++ b/packages/cli-module-new/README.md @@ -0,0 +1,14 @@ +# @backstage/cli-module-new + +CLI module that provides the `new` command for the Backstage CLI, offering an interactive guide to scaffold new plugins, packages, and modules in your Backstage app. + +## Commands + +| Command | Description | +| :------ | :-------------------------------------------------------------- | +| `new` | Open up an interactive guide to creating new things in your app | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/cli-module-test-jest/README.md b/packages/cli-module-test-jest/README.md new file mode 100644 index 0000000000..e56ffea2a7 --- /dev/null +++ b/packages/cli-module-test-jest/README.md @@ -0,0 +1,15 @@ +# @backstage/cli-module-test-jest + +CLI module that provides Jest-based testing commands for the Backstage CLI. + +## Commands + +| Command | Description | +| :------------- | :---------------------------------------------------------------- | +| `package test` | Run tests, forwarding arguments to Jest, defaulting to watch mode | +| `repo test` | Run tests, forwarding arguments to Jest, defaulting to watch mode | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) diff --git a/packages/cli-module-translations/README.md b/packages/cli-module-translations/README.md new file mode 100644 index 0000000000..1f415ca975 --- /dev/null +++ b/packages/cli-module-translations/README.md @@ -0,0 +1,15 @@ +# @backstage/cli-module-translations + +CLI module that provides translation management commands for the Backstage CLI. + +## Commands + +| Command | Description | +| :-------------------- | :------------------------------------------------------------------------------------ | +| `translations export` | Export translation messages from an app and all of its frontend plugins to JSON files | +| `translations import` | Generate translation resource wiring from translated JSON files | + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://backstage.io/docs) From 7879215cca3e0a2d9a6ac34c43929c467b113a89 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 21:16:00 +0100 Subject: [PATCH 34/45] Add CLI module deduplication and improve conflict reporting Individual CLI modules now silently take precedence over array-sourced modules (e.g. from cli-defaults) when their commands overlap. Conflict errors between non-array modules include both package names for easier debugging. Commands reference their parent module instead of storing a raw package name string. createCliModule now validates that packageJson has a name. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-defaults/report.api.md | 13 ++ packages/cli-defaults/src/index.ts | 5 + .../cli-internal/src/InternalCommandNode.ts | 3 +- .../src/cli-module/createCliModule.ts | 6 + .../cli/src/wiring/CliInitializer.test.ts | 134 ++++++++++++++++++ packages/cli/src/wiring/CliInitializer.ts | 59 +++++--- packages/cli/src/wiring/CommandGraph.ts | 45 +++++- 7 files changed, 244 insertions(+), 21 deletions(-) create mode 100644 packages/cli-defaults/report.api.md diff --git a/packages/cli-defaults/report.api.md b/packages/cli-defaults/report.api.md new file mode 100644 index 0000000000..573f8ee454 --- /dev/null +++ b/packages/cli-defaults/report.api.md @@ -0,0 +1,13 @@ +## API Report File for "@backstage/cli-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CliModule } from '@backstage/cli-node'; + +// @public +const _default: CliModule[]; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/cli-defaults/src/index.ts b/packages/cli-defaults/src/index.ts index 95c9052b1d..0126d0c074 100644 --- a/packages/cli-defaults/src/index.ts +++ b/packages/cli-defaults/src/index.ts @@ -25,6 +25,11 @@ import newModule from '@backstage/cli-module-new'; import testJest from '@backstage/cli-module-test-jest'; import translations from '@backstage/cli-module-translations'; +/** + * The default set of CLI modules for the Backstage CLI. + * + * @public + */ export default [ auth, build, diff --git a/packages/cli-internal/src/InternalCommandNode.ts b/packages/cli-internal/src/InternalCommandNode.ts index 3d93a5128d..bfa1f90baa 100644 --- a/packages/cli-internal/src/InternalCommandNode.ts +++ b/packages/cli-internal/src/InternalCommandNode.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { CliCommand } from '@backstage/cli-node'; +import { CliCommand, CliModule } from '@backstage/cli-node'; import { OpaqueType } from '@internal/opaque'; /** @internal */ @@ -47,6 +47,7 @@ export const OpaqueCommandLeafNode = OpaqueType.create<{ readonly version: 'v1'; readonly name: string; readonly command: CliCommand; + readonly module?: CliModule; }; }>({ type: '@backstage/CommandLeafNode', diff --git a/packages/cli-node/src/cli-module/createCliModule.ts b/packages/cli-node/src/cli-module/createCliModule.ts index 89ed21876f..7d52e9bf43 100644 --- a/packages/cli-node/src/cli-module/createCliModule.ts +++ b/packages/cli-node/src/cli-module/createCliModule.ts @@ -55,6 +55,12 @@ export function createCliModule(options: { addCommand: (command: CliCommand) => void; }) => Promise; }): CliModule { + if (!options.packageJson.name) { + throw new Error( + 'The packageJson provided to createCliModule must have a name', + ); + } + const commands: CliCommand[] = []; const commandsPromise = options .init({ addCommand: command => commands.push(command) }) diff --git a/packages/cli/src/wiring/CliInitializer.test.ts b/packages/cli/src/wiring/CliInitializer.test.ts index b5ac9cfaaa..703ec972fc 100644 --- a/packages/cli/src/wiring/CliInitializer.test.ts +++ b/packages/cli/src/wiring/CliInitializer.test.ts @@ -19,6 +19,24 @@ import { createCliModule } from './factory'; process.exit = jest.fn() as any; +describe('createCliModule', () => { + it('should throw if packageJson has no name', () => { + expect(() => + createCliModule({ + packageJson: { name: '' }, + init: async () => {}, + }), + ).toThrow('The packageJson provided to createCliModule must have a name'); + + expect(() => + createCliModule({ + packageJson: {} as any, + init: async () => {}, + }), + ).toThrow('The packageJson provided to createCliModule must have a name'); + }); +}); + describe('CliInitializer', () => { beforeEach(() => { jest.resetAllMocks(); @@ -239,4 +257,120 @@ describe('CliInitializer', () => { await initializer.run(); expect(process.exit).toHaveBeenCalledWith(0); }); + + it('should silently override array-sourced module with conflicting individual module while keeping siblings', async () => { + expect.assertions(3); + process.argv = ['node', 'cli', 'test']; + const initializer = new CliInitializer(); + + const individualModule = createCliModule({ + packageJson: { name: '@backstage/individual' }, + init: async reg => + reg.addCommand({ + path: ['test'], + description: 'individual test', + execute: ({ args }) => { + expect(args).toEqual([]); + return Promise.resolve(); + }, + }), + }); + + const conflictingArrayModule = createCliModule({ + packageJson: { name: '@backstage/array-conflict' }, + init: async reg => + reg.addCommand({ + path: ['test'], + description: 'array test (should be skipped)', + execute: () => Promise.resolve(), + }), + }); + + const nonConflictingArrayModule = createCliModule({ + packageJson: { name: '@backstage/array-sibling' }, + init: async reg => + reg.addCommand({ + path: ['other'], + description: 'other command', + execute: () => Promise.resolve(), + }), + }); + + initializer.add(individualModule); + initializer.add([conflictingArrayModule, nonConflictingArrayModule]); + + await initializer.run(); + expect(process.exit).toHaveBeenCalledWith(0); + + // Verify the sibling command is available by running it + process.argv = ['node', 'cli', 'other']; + const initializer2 = new CliInitializer(); + initializer2.add(individualModule); + initializer2.add([conflictingArrayModule, nonConflictingArrayModule]); + await initializer2.run(); + expect(process.exit).toHaveBeenCalledTimes(2); + }); + + it('should error with package names when two individual modules conflict', async () => { + const initializer = new CliInitializer(); + + initializer.add( + createCliModule({ + packageJson: { name: '@backstage/module-a' }, + init: async reg => + reg.addCommand({ + path: ['conflicting'], + description: 'from module A', + execute: () => Promise.resolve(), + }), + }), + ); + + initializer.add( + createCliModule({ + packageJson: { name: '@backstage/module-b' }, + init: async reg => + reg.addCommand({ + path: ['conflicting'], + description: 'from module B', + execute: () => Promise.resolve(), + }), + }), + ); + + await expect(initializer.run()).rejects.toThrow( + 'Command "conflicting" from "@backstage/module-b" conflicts with an existing command from "@backstage/module-a"', + ); + }); + + it('should error with package names when two array-sourced modules conflict', async () => { + const initializer = new CliInitializer(); + + const moduleA = createCliModule({ + packageJson: { name: '@backstage/array-a' }, + init: async reg => + reg.addCommand({ + path: ['shared'], + description: 'from array A', + execute: () => Promise.resolve(), + }), + }); + + const moduleB = createCliModule({ + packageJson: { name: '@backstage/array-b' }, + init: async reg => + reg.addCommand({ + path: ['shared'], + description: 'from array B', + execute: () => Promise.resolve(), + }), + }); + + initializer.add([moduleA]); + initializer.add([moduleB]); + + await expect(initializer.run()).rejects.toThrow( + 'Command "shared" from "@backstage/array-b" conflicts with an existing command from "@backstage/array-a"', + ); + }); }); diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index 4e1067d780..e2c46cf99b 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -22,7 +22,6 @@ import { } from '@internal/cli'; import type { CommandNode } from '@internal/cli'; import type { CliModule } from '@backstage/cli-node'; -import { CommandRegistry } from './CommandRegistry'; import { Command } from 'commander'; import { version } from './version'; import chalk from 'chalk'; @@ -44,28 +43,42 @@ type UninitializedFeature = | CliModule[] | Promise<{ default: CliModule | CliModule[] }>; +interface TaggedFeature { + feature: CliModule; + fromArray: boolean; +} + export class CliInitializer { private graph = new CommandGraph(); - private commandRegistry = new CommandRegistry(this.graph); - #uninitiazedFeatures: Promise[] = []; + #uninitiazedFeatures: Promise[] = []; add(feature: UninitializedFeature) { if (isPromise(feature)) { this.#uninitiazedFeatures.push( - feature.then(f => unwrapFeature(f.default)), + feature.then(f => { + const unwrapped = unwrapFeature(f.default); + if (Array.isArray(unwrapped)) { + return unwrapped.map(m => ({ feature: m, fromArray: true })); + } + return [{ feature: unwrapped, fromArray: false }]; + }), ); } else if (Array.isArray(feature)) { - this.#uninitiazedFeatures.push(Promise.resolve(feature)); + this.#uninitiazedFeatures.push( + Promise.resolve(feature.map(m => ({ feature: m, fromArray: true }))), + ); } else { - this.#uninitiazedFeatures.push(Promise.resolve(feature)); + this.#uninitiazedFeatures.push( + Promise.resolve([{ feature, fromArray: false }]), + ); } } async #register(feature: CliModule) { if (OpaqueCliModule.isType(feature)) { - const internal = OpaqueCliModule.toInternal(feature); - for (const command of await internal.commands) { - this.commandRegistry.addCommand(command); + for (const command of await OpaqueCliModule.toInternal(feature) + .commands) { + this.graph.add(command, feature); } } else { throw new Error(`Unsupported feature type: ${(feature as any).$$type}`); @@ -73,15 +86,29 @@ export class CliInitializer { } async #doInit() { - const resolved = await Promise.all(this.#uninitiazedFeatures); - for (const featureOrArray of resolved) { - const features = Array.isArray(featureOrArray) - ? featureOrArray - : [featureOrArray]; - for (const feature of features) { - await this.#register(feature); + const resolvedGroups = await Promise.all(this.#uninitiazedFeatures); + const allFeatures = resolvedGroups.flat(); + + // Collect command paths from individually-added modules + const individualPaths = new Set(); + for (const { feature, fromArray } of allFeatures) { + if (!fromArray && OpaqueCliModule.isType(feature)) { + const cmds = await OpaqueCliModule.toInternal(feature).commands; + for (const cmd of cmds) { + individualPaths.add(cmd.path.join(' ')); + } } } + + for (const { feature, fromArray } of allFeatures) { + if (fromArray && OpaqueCliModule.isType(feature)) { + const cmds = await OpaqueCliModule.toInternal(feature).commands; + if (cmds.some(cmd => individualPaths.has(cmd.path.join(' ')))) { + continue; + } + } + await this.#register(feature); + } } /** diff --git a/packages/cli/src/wiring/CommandGraph.ts b/packages/cli/src/wiring/CommandGraph.ts index b3db5d68bb..b201a3fba3 100644 --- a/packages/cli/src/wiring/CommandGraph.ts +++ b/packages/cli/src/wiring/CommandGraph.ts @@ -17,8 +17,9 @@ import { CommandNode, OpaqueCommandTreeNode, OpaqueCommandLeafNode, + OpaqueCliModule, } from '@internal/cli'; -import { CliCommand } from './types'; +import { CliCommand, CliModule } from './types'; /** * A sparse graph of commands. @@ -30,7 +31,7 @@ export class CommandGraph { * Adds a command to the graph. The graph is sparse, so we use the path to determine the nodes * to traverse. Only leaf nodes should have a command/action. */ - add(command: CliCommand) { + add(command: CliCommand, module?: CliModule) { const path = command.path; let current = this.graph; for (let i = 0; i < path.length - 1; i++) { @@ -50,7 +51,11 @@ export class CommandGraph { current.push(next); } else if (OpaqueCommandLeafNode.isType(next)) { throw new Error( - `Command already exists at path: "${path.slice(0, i).join(' ')}"`, + formatConflictError( + path, + module, + OpaqueCommandLeafNode.toInternal(next).module, + ), ); } current = OpaqueCommandTreeNode.toInternal(next).children; @@ -64,13 +69,18 @@ export class CommandGraph { }); if (last && OpaqueCommandLeafNode.isType(last)) { throw new Error( - `Command already exists at path: "${path.slice(0, -1).join(' ')}"`, + formatConflictError( + path, + module, + OpaqueCommandLeafNode.toInternal(last).module, + ), ); } else { current.push( OpaqueCommandLeafNode.createInstance('v1', { name: lastName, command, + module, }), ); } @@ -119,3 +129,30 @@ export class CommandGraph { return current; } } + +function getModuleName(module?: CliModule): string | undefined { + if (module && OpaqueCliModule.isType(module)) { + return OpaqueCliModule.toInternal(module).packageName; + } + return undefined; +} + +function formatConflictError( + path: string[], + newModule?: CliModule, + existingModule?: CliModule, +): string { + const cmd = path.join(' '); + const newPkg = getModuleName(newModule); + const existingPkg = getModuleName(existingModule); + if (newPkg && existingPkg) { + return `Command "${cmd}" from "${newPkg}" conflicts with an existing command from "${existingPkg}"`; + } + if (newPkg) { + return `Command "${cmd}" from "${newPkg}" conflicts with an existing command`; + } + if (existingPkg) { + return `Command "${cmd}" conflicts with an existing command from "${existingPkg}"`; + } + return `Command "${cmd}" conflicts with an existing command`; +} From 2069f642018dcb41f489eeee04ed712b40bcb57a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 21:51:07 +0100 Subject: [PATCH 35/45] Remove extra exports from CLI module packages CLI modules should only export the module itself as a default export. Remove the named `buildPlugin` export from cli-module-build and the unused `configOption` export from cli-module-config. Also remove the API report warning skip for CLI module packages. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- package.json | 8 ++++---- packages/cli-module-build/report.api.md | 7 ++----- packages/cli-module-build/src/index.ts | 4 +--- packages/cli-module-config/report.api.md | 10 ---------- packages/cli-module-config/src/index.ts | 7 ------- 5 files changed, 7 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index a302681d2f..c443b8aa81 100644 --- a/package.json +++ b/package.json @@ -21,15 +21,15 @@ "plugins/*" ], "scripts": { - "build-storybook": "storybook build --output-dir dist-storybook", - "build-storybook:chromatic": "STORYBOOK_STORY_SET=chromatic storybook build --stats-json --output-dir dist-storybook", "build:all": "backstage-cli repo build --all", "build:api-docs": "LANG=en_EN yarn build:api-reports --docs --exclude 'plugins/@(api-docs|api-docs-module-protoc-gen-doc|app-visualizer|catalog-graph|catalog-import|catalog-unprocessed-entities|config-schema|example-todo-list|example-todo-list-backend)'", "build:api-reports": "yarn build:api-reports:only --tsc", - "build:api-reports:only": "LANG=en_US.UTF-8 NODE_OPTIONS=--max-old-space-size=8192 backstage-repo-tools api-reports --sql-reports --allow-warnings 'packages/backend-app-api,packages/cli-module-*,packages/core-components,plugins/+(catalog|catalog-import|kubernetes)' -o ae-undocumented,ae-wrong-input-file-type --validate-release-tags", + "build:api-reports:only": "LANG=en_US.UTF-8 NODE_OPTIONS=--max-old-space-size=8192 backstage-repo-tools api-reports --sql-reports --allow-warnings 'packages/backend-app-api,packages/core-components,plugins/+(catalog|catalog-import|kubernetes)' -o ae-undocumented,ae-wrong-input-file-type --validate-release-tags", "build:backend": "yarn workspace example-backend build", "build:knip-reports": "backstage-repo-tools knip-reports", "build:plugins-report": "node ./scripts/build-plugins-report", + "build-storybook": "storybook build --output-dir dist-storybook", + "build-storybook:chromatic": "STORYBOOK_STORY_SET=chromatic storybook build --stats-json --output-dir dist-storybook", "clean": "backstage-cli repo clean", "create-plugin": "echo \"use 'yarn new' instead\"", "dev": "echo \"use 'yarn start' instead\"", @@ -52,10 +52,10 @@ "snyk:test": "npx snyk test --yarn-workspaces --strict-out-of-sync=false", "snyk:test:package": "yarn snyk:test --include", "start": "backstage-cli repo start", - "start-backend": "echo \"Use 'yarn start example-backend' instead\"", "start:docker": "docker compose -f docker-compose.deps.yml up --wait && BACKSTAGE_ENV=docker yarn start", "start:legacy": "yarn start example-app-legacy example-backend", "start:microsite": "cd microsite/ && yarn start", + "start-backend": "echo \"Use 'yarn start example-backend' instead\"", "storybook": "storybook dev -p 6006", "sync-issue-templates": "node ./.github/ISSUE_TEMPLATE/sync.js", "techdocs-cli": "node scripts/techdocs-cli.js", diff --git a/packages/cli-module-build/report.api.md b/packages/cli-module-build/report.api.md index 6309f5b839..34634dd448 100644 --- a/packages/cli-module-build/report.api.md +++ b/packages/cli-module-build/report.api.md @@ -5,12 +5,9 @@ ```ts import { CliModule } from '@backstage/cli-node'; -// Warning: (ae-missing-release-tag) "buildPlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -const buildPlugin: CliModule; -export { buildPlugin }; -export default buildPlugin; +const _default: CliModule; +export default _default; // (No @packageDocumentation comment for this package) ``` diff --git a/packages/cli-module-build/src/index.ts b/packages/cli-module-build/src/index.ts index b2fb597249..887a4b562c 100644 --- a/packages/cli-module-build/src/index.ts +++ b/packages/cli-module-build/src/index.ts @@ -17,7 +17,7 @@ import { createCliModule } from '@backstage/cli-node'; import packageJson from '../package.json'; -export const buildPlugin = createCliModule({ +export default createCliModule({ packageJson, init: async reg => { reg.addCommand({ @@ -85,5 +85,3 @@ export const buildPlugin = createCliModule({ }); }, }); - -export default buildPlugin; diff --git a/packages/cli-module-config/report.api.md b/packages/cli-module-config/report.api.md index 185bec4e05..740aef21fb 100644 --- a/packages/cli-module-config/report.api.md +++ b/packages/cli-module-config/report.api.md @@ -5,16 +5,6 @@ ```ts import { CliModule } from '@backstage/cli-node'; -// Warning: (ae-missing-release-tag) "configOption" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const configOption: readonly [ - '--config ', - 'Config files to load instead of app-config.yaml', - (opt: string, opts: string[]) => string[], - string[], -]; - // @public (undocumented) const _default: CliModule; export default _default; diff --git a/packages/cli-module-config/src/index.ts b/packages/cli-module-config/src/index.ts index af2a7143b7..a041f32d6e 100644 --- a/packages/cli-module-config/src/index.ts +++ b/packages/cli-module-config/src/index.ts @@ -16,13 +16,6 @@ import { createCliModule } from '@backstage/cli-node'; import packageJson from '../package.json'; -export const configOption = [ - '--config ', - 'Config files to load instead of app-config.yaml', - (opt: string, opts: string[]) => (opts ? [...opts, opt] : [opt]), - Array(), -] as const; - export default createCliModule({ packageJson, init: async reg => { From 00adaa9902632d16b61731539a680e084d576108 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 22:01:41 +0100 Subject: [PATCH 36/45] Restore findOwnPaths for serve_index.html in build module Move serve_index.html to cli-module-build/templates and use findOwnPaths instead of require.resolve for safer path resolution. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-build/package.json | 7 ++--- .../cli-module-build/src/lib/bundler/paths.ts | 6 +++-- .../templates/serve_index.html | 27 +++++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 packages/cli-module-build/templates/serve_index.html diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index 7591007756..7f9fa0b37b 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -19,9 +19,11 @@ "license": "Apache-2.0", "main": "src/index.ts", "types": "src/index.ts", + "bin": "bin/cli-module-build", "files": [ "dist", - "bin" + "bin", + "templates" ], "scripts": { "build": "backstage-cli package build", @@ -98,6 +100,5 @@ "@types/lodash": "^4.14.151", "@types/npm-packlist": "^3.0.0", "@types/shell-quote": "^1.7.5" - }, - "bin": "bin/cli-module-build" + } } diff --git a/packages/cli-module-build/src/lib/bundler/paths.ts b/packages/cli-module-build/src/lib/bundler/paths.ts index d479f74061..5a7d3b14dc 100644 --- a/packages/cli-module-build/src/lib/bundler/paths.ts +++ b/packages/cli-module-build/src/lib/bundler/paths.ts @@ -16,7 +16,7 @@ import fs from 'fs-extra'; import { resolve as resolvePath } from 'node:path'; -import { targetPaths } from '@backstage/cli-common'; +import { targetPaths, findOwnPaths } from '@backstage/cli-common'; export type BundlingPathsOptions = { // bundle entrypoint, e.g. 'src/index' @@ -50,7 +50,9 @@ export function resolveBundlingPaths(options: BundlingPathsOptions) { targetHtml = resolvePath(targetDir, `${entry}.html`); if (!fs.pathExistsSync(targetHtml)) { /* eslint-disable-next-line no-restricted-syntax */ - targetHtml = require.resolve('@backstage/cli/templates/serve_index.html'); + targetHtml = findOwnPaths(__dirname).resolve( + 'templates/serve_index.html', + ); } } diff --git a/packages/cli-module-build/templates/serve_index.html b/packages/cli-module-build/templates/serve_index.html new file mode 100644 index 0000000000..bc91f1bc04 --- /dev/null +++ b/packages/cli-module-build/templates/serve_index.html @@ -0,0 +1,27 @@ + + + + + + + + Backstage + + + +
+ + + From 55f6eb8c6443c64816290afdc6837c275217b0a5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 22:11:43 +0100 Subject: [PATCH 37/45] Move config files to CLI modules with lazy proxies Move jest config files to cli-module-test-jest/config and node transform + webpack-public-path to cli-module-build/config. Replace originals in @backstage/cli/config with lazy proxies that forward to the appropriate module or throw if it is not installed. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-build/.eslintrc.js | 4 +- .../cli-module-build/config/nodeTransform.cjs | 87 ++++ .../config/nodeTransformHooks.mjs | 294 ++++++++++++ .../config/webpack-public-path.js | 31 ++ packages/cli-module-build/package.json | 3 + .../src/lib/bundler/config.ts | 5 +- .../src/lib/runner/runBackend.ts | 5 +- .../src/tests/transforms/transforms.test.ts | 4 +- packages/cli-module-test-jest/.eslintrc.js | 4 +- .../config/getJestEnvironment.js | 49 ++ .../config/jest-environment-jsdom/index.js | 61 +++ packages/cli-module-test-jest/config/jest.js | 422 ++++++++++++++++++ .../config/jestCacheResultProcessor.cjs | 23 + .../config/jestCachingModuleLoader.js | 35 ++ .../config/jestFileTransform.js | 44 ++ .../config/jestRejectNetworkRequests.js | 70 +++ .../config/jestSucraseTransform.js | 87 ++++ .../config/jestSwcTransform.js | 44 ++ .../config/jestYamlTransform.js | 40 ++ packages/cli-module-test-jest/package.json | 26 +- .../src/commands/package/test.ts | 4 +- .../src/commands/repo/test.ts | 3 +- packages/cli/config/getJestEnvironment.js | 36 +- .../config/jest-environment-jsdom/index.js | 52 +-- packages/cli/config/jest.js | 409 +---------------- .../cli/config/jestCacheResultProcessor.cjs | 16 +- .../cli/config/jestCachingModuleLoader.js | 30 +- packages/cli/config/jestFileTransform.js | 39 +- .../cli/config/jestRejectNetworkRequests.js | 63 +-- packages/cli/config/jestSucraseTransform.js | 80 +--- packages/cli/config/jestSwcTransform.js | 37 +- packages/cli/config/jestYamlTransform.js | 35 +- packages/cli/config/nodeTransform.cjs | 80 +--- packages/cli/config/nodeTransformHooks.mjs | 282 +----------- packages/cli/config/webpack-public-path.js | 24 +- packages/cli/package.json | 2 + yarn.lock | 21 + 37 files changed, 1476 insertions(+), 1075 deletions(-) create mode 100644 packages/cli-module-build/config/nodeTransform.cjs create mode 100644 packages/cli-module-build/config/nodeTransformHooks.mjs create mode 100644 packages/cli-module-build/config/webpack-public-path.js create mode 100644 packages/cli-module-test-jest/config/getJestEnvironment.js create mode 100644 packages/cli-module-test-jest/config/jest-environment-jsdom/index.js create mode 100644 packages/cli-module-test-jest/config/jest.js create mode 100644 packages/cli-module-test-jest/config/jestCacheResultProcessor.cjs create mode 100644 packages/cli-module-test-jest/config/jestCachingModuleLoader.js create mode 100644 packages/cli-module-test-jest/config/jestFileTransform.js create mode 100644 packages/cli-module-test-jest/config/jestRejectNetworkRequests.js create mode 100644 packages/cli-module-test-jest/config/jestSucraseTransform.js create mode 100644 packages/cli-module-test-jest/config/jestSwcTransform.js create mode 100644 packages/cli-module-test-jest/config/jestYamlTransform.js diff --git a/packages/cli-module-build/.eslintrc.js b/packages/cli-module-build/.eslintrc.js index e2a53a6ad2..a070dc55ee 100644 --- a/packages/cli-module-build/.eslintrc.js +++ b/packages/cli-module-build/.eslintrc.js @@ -1 +1,3 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + ignorePatterns: ['config/**', 'templates/**'], +}); diff --git a/packages/cli-module-build/config/nodeTransform.cjs b/packages/cli-module-build/config/nodeTransform.cjs new file mode 100644 index 0000000000..15bcdba9bc --- /dev/null +++ b/packages/cli-module-build/config/nodeTransform.cjs @@ -0,0 +1,87 @@ +/* + * 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. + */ + +const { pathToFileURL } = require('node:url'); +const { transformSync } = require('@swc/core'); +const { addHook } = require('pirates'); +const { Module } = require('node:module'); + +// This hooks into module resolution and overrides imports of packages that +// exist in the linked workspace to instead be resolved from the linked workspace. +if (process.env.BACKSTAGE_CLI_LINKED_WORKSPACE) { + const { join: joinPath } = require('node:path'); + const { getPackagesSync } = require('@manypkg/get-packages'); + const { packages: linkedPackages, root: linkedRoot } = getPackagesSync( + process.env.BACKSTAGE_CLI_LINKED_WORKSPACE, + ); + + // Matches all packages in the linked workspaces, as well as sub-path exports from them + const replacementRegex = new RegExp( + `^(?:${linkedPackages + .map(pkg => pkg.packageJson.name) + .join('|')})(?:/.*)?$`, + ); + + const origLoad = Module._load; + Module._load = function requireHook(request, parent) { + if (!replacementRegex.test(request)) { + return origLoad.call(this, request, parent); + } + + // The package import that we're overriding will always existing in the root + // node_modules of the linked workspace, so it's enough to override the + // parent paths with that single entry + return origLoad.call(this, request, { + ...parent, + paths: [joinPath(linkedRoot.dir, 'node_modules')], + }); + }; +} + +addHook( + (code, filename) => { + const transformed = transformSync(code, { + filename, + sourceMaps: 'inline', + module: { + type: 'commonjs', + ignoreDynamic: true, + }, + jsc: { + target: 'es2023', + parser: { + syntax: 'typescript', + }, + }, + }); + process.send?.({ type: 'watch', path: filename }); + return transformed.code; + }, + { extensions: ['.ts', '.cts'], ignoreNodeModules: true }, +); + +addHook( + (code, filename) => { + process.send?.({ type: 'watch', path: filename }); + return code; + }, + { extensions: ['.js', '.cjs'], ignoreNodeModules: true }, +); + +// Register module hooks, used by "type": "module" in package.json, .mjs and +// .mts files, as well as dynamic import(...)s, although dynamic imports will be +// handled be the CommonJS hooks in this file if what it points to is CommonJS. +Module.register('./nodeTransformHooks.mjs', pathToFileURL(__filename)); diff --git a/packages/cli-module-build/config/nodeTransformHooks.mjs b/packages/cli-module-build/config/nodeTransformHooks.mjs new file mode 100644 index 0000000000..592867e57a --- /dev/null +++ b/packages/cli-module-build/config/nodeTransformHooks.mjs @@ -0,0 +1,294 @@ +/* + * 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 { dirname, extname, resolve as resolvePath } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { transformFile } from '@swc/core'; +import { isBuiltin } from 'node:module'; +import { readFile } from 'node:fs/promises'; +import { existsSync } from 'node:fs'; + +// @ts-check + +// No explicit file extension, no type in package.json +const DEFAULT_MODULE_FORMAT = 'commonjs'; + +// Source file extensions to look for when using bundle resolution strategy +const SRC_EXTS = ['.ts', '.js']; +const TS_EXTS = ['.ts', '.mts', '.cts']; +const moduleTypeTable = { + '.mjs': 'module', + '.mts': 'module', + '.cjs': 'commonjs', + '.cts': 'commonjs', + '.ts': undefined, + '.js': undefined, +}; + +/** @type {import('module').ResolveHook} */ +export async function resolve(specifier, context, nextResolve) { + // Built-in modules are handled by the default resolver + if (isBuiltin(specifier)) { + return nextResolve(specifier, context); + } + + const ext = extname(specifier); + + // Unless there's an explicit import attribute, JSON files are loaded with our custom loader that's defined below. + if (ext === '.json' && !context.importAttributes?.type) { + const jsonResult = await nextResolve(specifier, context); + return { + ...jsonResult, + format: 'commonjs', + importAttributes: { type: 'json' }, + }; + } + + // Anything else with an explicit extension is handled by the default + // resolver, except that we help determine the module type where needed. + if (ext !== '') { + return withDetectedModuleType(await nextResolve(specifier, context)); + } + + // Other external modules are handled by the default resolver, but again we + // help determine the module type where needed. + if (!specifier.startsWith('.')) { + return withDetectedModuleType(await nextResolve(specifier, context)); + } + + // The rest of this function handles the case of resolving imports that do not + // specify any extension and might point to a directory with an `index.*` + // file. We resolve those using the same logic as most JS bundlers would, with + // the addition of checking if there's an explicit module format listed in the + // closest `package.json` file. + // + // We use a bundle resolution strategy in order to keep code consistent across + // Backstage codebases that contains code both for Web and Node.js, and to + // support packages with common code that can be used in both environments. + try { + // This is expected to throw, but in the event that this module specifier is + // supported we prefer to use the default resolver. + return await nextResolve(specifier, context); + } catch (error) { + if (error.code === 'ERR_UNSUPPORTED_DIR_IMPORT') { + const spec = `${specifier}${specifier.endsWith('/') ? '' : '/'}index`; + const resolved = await resolveWithoutExt(spec, context, nextResolve); + if (resolved) { + return withDetectedModuleType(resolved); + } + } else if (error.code === 'ERR_MODULE_NOT_FOUND') { + const resolved = await resolveWithoutExt(specifier, context, nextResolve); + if (resolved) { + return withDetectedModuleType(resolved); + } + } + + // Unexpected error or no resolution found + throw error; + } +} + +/** + * Populates the `format` field in the resolved object based on the closest `package.json` file. + * + * @param {import('module').ResolveFnOutput} resolved + * @returns {Promise} + */ +async function withDetectedModuleType(resolved) { + // Already has an explicit format + if (resolved.format) { + return resolved; + } + // Happens in Node.js v22 when there's a package.json without an explicit "type" field. Use the default. + if (resolved.format === null) { + return { ...resolved, format: DEFAULT_MODULE_FORMAT }; + } + + const ext = extname(resolved.url); + + const explicitFormat = moduleTypeTable[ext]; + if (explicitFormat) { + return { + ...resolved, + format: explicitFormat, + }; + } + + // Under normal circumstances .js files should reliably have a format and so + // we should only reach this point for .ts files. However, if additional + // custom loaders are being used the format may not be detected for .js files + // either. As such we don't restrict the file format at this point. + + // TODO(Rugvip): Does this need caching? kept it simple for now but worth exploring + const packageJsonPath = await findPackageJSON(fileURLToPath(resolved.url)); + if (!packageJsonPath) { + return resolved; + } + + const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8')); + return { + ...resolved, + format: packageJson.type ?? DEFAULT_MODULE_FORMAT, + }; +} + +/** + * Find the closest package.json file from the given path. + * + * TODO(Rugvip): This can be replaced with the Node.js built-in with the same name once it is stable. + * @param {string} startPath + * @returns {Promise} + */ +async function findPackageJSON(startPath) { + let path = startPath; + + // Some confidence check to avoid infinite loop + for (let i = 0; i < 1000; i++) { + const packagePath = resolvePath(path, 'package.json'); + if (existsSync(packagePath)) { + return packagePath; + } + + const newPath = dirname(path); + if (newPath === path) { + return undefined; + } + path = newPath; + } + + throw new Error( + `Iteration limit reached when searching for package.json at ${startPath}`, + ); +} + +/** @type {import('module').ResolveHook} */ +async function resolveWithoutExt(specifier, context, nextResolve) { + for (const tryExt of SRC_EXTS) { + try { + const resolved = await nextResolve(specifier + tryExt, { + ...context, + format: 'commonjs', + }); + return { + ...resolved, + format: moduleTypeTable[tryExt] ?? resolved.format, + }; + } catch { + /* ignore */ + } + } + return undefined; +} + +/** @type {import('module').LoadHook} */ +export async function load(url, context, nextLoad) { + // Non-file URLs are handled by the default loader + if (!url.startsWith('file://')) { + return nextLoad(url, context); + } + + // JSON files loaded as CommonJS are handled by this custom loader, because + // the default one doesn't work. For JSON loading to work we'd need the + // synchronous hooks that aren't supported yet, or avoid using the CommonJS + // compatibility. + if ( + context.format === 'commonjs' && + context.importAttributes?.type === 'json' + ) { + try { + // TODO(Rugvip): Make sure this is valid JSON + const content = await readFile(fileURLToPath(url), 'utf8'); + return { + source: `module.exports = (${content})`, + format: 'commonjs', + shortCircuit: true, + }; + } catch { + // Let the default loader generate the error + return nextLoad(url, context); + } + } + + const ext = extname(url); + + // Non-TS files are handled by the default loader + if (!TS_EXTS.includes(ext)) { + return nextLoad(url, context); + } + + const format = context.format ?? DEFAULT_MODULE_FORMAT; + + // We have two choices at this point, we can either transform CommonJS files + // and return the transformed source code, or let the default loader handle + // them. If we transform them ourselves we will enter CommonJS compatibility + // mode in the new module system in Node.js, this effectively means all + // CommonJS loaded via `require` calls from this point will all be treated as + // if it was loaded via `import` calls from modules. + // + // The CommonJS compatibility layer will try to identify named exports and + // make them available directly, which is convenient as it avoids things like + // `import(...).then(m => m.default.foo)`, allowing you to instead write + // `import(...).then(m => m.foo)`. The compatibility layer doesn't always work + // all that well though, and can lead to module loading issues in many cases, + // especially for older code. + + // This `if` block opts-out of using CommonJS compatibility mode by default, + // and instead leaves it to our existing loader to transform CommonJS. We do + // however use compatibility mode for the more explicit .cts file extension, + // allows for a way to opt-in to the new behavior. + // + // TODO(Rugvip): Once the synchronous hooks API is available for us to use, we might be able to adopt that instead + if (format === 'commonjs' && ext !== '.cts') { + return nextLoad(url, { ...context, format }); + } + + // If the Node.js version we're running supports TypeScript, i.e. type + // stripping, we hand over to the default loader. This is done for all cases + // except if we're loading a .ts file that's been resolved to CommonJS format. + // This is because these files aren't actually CommonJS in the Backstage build + // system, and need to be transformed to CommonJS. + if ( + format === 'module-typescript' || + (format === 'module-commonjs' && ext !== '.ts') + ) { + return nextLoad(url, { ...context, format }); + } + + const transformed = await transformFile(fileURLToPath(url), { + sourceMaps: 'inline', + module: { + type: format === 'module' ? 'es6' : 'commonjs', + ignoreDynamic: true, + + // This helps the Node.js CommonJS compat layer identify named exports. + exportInteropAnnotation: true, + }, + jsc: { + target: 'es2023', + parser: { + syntax: 'typescript', + }, + }, + }); + + return { + ...context, + shortCircuit: true, + source: transformed.code, + format, + responseURL: url, + }; +} diff --git a/packages/cli-module-build/config/webpack-public-path.js b/packages/cli-module-build/config/webpack-public-path.js new file mode 100644 index 0000000000..3e14e96eb9 --- /dev/null +++ b/packages/cli-module-build/config/webpack-public-path.js @@ -0,0 +1,31 @@ +/* + * 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. + */ + +// This script is used to pick up and set the public path of the Webpack bundle +// at runtime. The meta tag is injected by the app build, but only present in +// the `index.html.tmpl` file. The runtime value of the meta tag is populated by +// the app backend, when it templates the final `index.html` file. +// +// This is needed for additional chunks to use the correct public path, and it +// is not possible to set the `__webpack_public_path__` variable outside of the +// build itself. The Webpack output also does not read any tags or +// similar, this seems to be the only way to dynamically configure the public +// path at runtime. +const el = document.querySelector('meta[name="backstage-public-path"]'); +const path = el?.getAttribute('content'); +if (path) { + __webpack_public_path__ = path; +} diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index 7f9fa0b37b..519b24b701 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -23,6 +23,7 @@ "files": [ "dist", "bin", + "config", "templates" ], "scripts": { @@ -50,6 +51,7 @@ "@rspack/core": "^1.4.11", "@rspack/dev-server": "^1.1.4", "@rspack/plugin-react-refresh": "^1.4.3", + "@swc/core": "^1.15.6", "bfj": "^9.0.2", "buffer": "^6.0.3", "chalk": "^4.0.0", @@ -70,6 +72,7 @@ "node-stdlib-browser": "^1.3.1", "npm-packlist": "^5.0.0", "p-queue": "^6.6.2", + "pirates": "^4.0.6", "postcss": "^8.1.0", "postcss-import": "^16.1.0", "process": "^0.11.10", diff --git a/packages/cli-module-build/src/lib/bundler/config.ts b/packages/cli-module-build/src/lib/bundler/config.ts index 08856cd63e..cee7ba6819 100644 --- a/packages/cli-module-build/src/lib/bundler/config.ts +++ b/packages/cli-module-build/src/lib/bundler/config.ts @@ -29,7 +29,7 @@ import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack'; import fs from 'fs-extra'; import { optimization as optimizationConfig } from './optimization'; import pickBy from 'lodash/pickBy'; -import { runOutput, targetPaths } from '@backstage/cli-common'; +import { findOwnPaths, runOutput, targetPaths } from '@backstage/cli-common'; import { transforms } from './transforms'; import { version } from '../../../package.json'; @@ -330,7 +330,8 @@ export async function createConfig( devtool: isDev ? 'eval-cheap-module-source-map' : 'source-map', context: paths.targetPath, entry: [ - require.resolve('@backstage/cli/config/webpack-public-path'), + /* eslint-disable-next-line no-restricted-syntax */ + findOwnPaths(__dirname).resolve('config/webpack-public-path'), ...(options.additionalEntryPoints ?? []), paths.targetEntry, ], diff --git a/packages/cli-module-build/src/lib/runner/runBackend.ts b/packages/cli-module-build/src/lib/runner/runBackend.ts index 22fd50b3f4..73c3fe08c7 100644 --- a/packages/cli-module-build/src/lib/runner/runBackend.ts +++ b/packages/cli-module-build/src/lib/runner/runBackend.ts @@ -21,14 +21,15 @@ import { IpcServer, ServerDataStore } from '../ipc'; import debounce from 'lodash/debounce'; import { fileURLToPath } from 'node:url'; import { isAbsolute as isAbsolutePath } from 'node:path'; -import { targetPaths } from '@backstage/cli-common'; +import { findOwnPaths, targetPaths } from '@backstage/cli-common'; import spawn from 'cross-spawn'; const loaderArgs = [ '--enable-source-maps', '--require', - require.resolve('@backstage/cli/config/nodeTransform.cjs'), + /* eslint-disable-next-line no-restricted-syntax */ + findOwnPaths(__dirname).resolve('config/nodeTransform.cjs'), // TODO: Support modules, although there's currently no way to load them since import() is transpiled tp require() ]; diff --git a/packages/cli-module-build/src/tests/transforms/transforms.test.ts b/packages/cli-module-build/src/tests/transforms/transforms.test.ts index 9e4fca8c63..40f40fac2d 100644 --- a/packages/cli-module-build/src/tests/transforms/transforms.test.ts +++ b/packages/cli-module-build/src/tests/transforms/transforms.test.ts @@ -16,6 +16,7 @@ import { execFileSync } from 'node:child_process'; import { resolve as resolvePath } from 'node:path'; +import { findOwnPaths } from '@backstage/cli-common'; import { Output, buildPackage } from '../../lib/builder'; const exportValues = { @@ -55,7 +56,8 @@ function loadFixture(fixture: string) { 'node', [ '--import', - '@backstage/cli/config/nodeTransform.cjs', + /* eslint-disable-next-line no-restricted-syntax */ + findOwnPaths(__dirname).resolve('config/nodeTransform.cjs'), resolvePath(__dirname, `__fixtures__/${fixture}`), ], { encoding: 'utf8' }, diff --git a/packages/cli-module-test-jest/.eslintrc.js b/packages/cli-module-test-jest/.eslintrc.js index e2a53a6ad2..6f313a7a5e 100644 --- a/packages/cli-module-test-jest/.eslintrc.js +++ b/packages/cli-module-test-jest/.eslintrc.js @@ -1 +1,3 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + ignorePatterns: ['config/**'], +}); diff --git a/packages/cli-module-test-jest/config/getJestEnvironment.js b/packages/cli-module-test-jest/config/getJestEnvironment.js new file mode 100644 index 0000000000..aac2f79021 --- /dev/null +++ b/packages/cli-module-test-jest/config/getJestEnvironment.js @@ -0,0 +1,49 @@ +/* + * Copyright 2025 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. + */ + +function getJestMajorVersion() { + const jestVersion = require('jest/package.json').version; + const majorVersion = parseInt(jestVersion.split('.')[0], 10); + return majorVersion; +} + +function getJestEnvironment() { + const majorVersion = getJestMajorVersion(); + + if (majorVersion >= 30) { + try { + require.resolve('@jest/environment-jsdom-abstract'); + require.resolve('jsdom'); + } catch { + throw new Error( + 'Jest 30+ requires @jest/environment-jsdom-abstract and jsdom. ' + + 'Please install them as dev dependencies.', + ); + } + return require.resolve('./jest-environment-jsdom'); + } + try { + require.resolve('jest-environment-jsdom'); + } catch { + throw new Error( + 'Jest 29 requires jest-environment-jsdom. ' + + 'Please install it as a dev dependency.', + ); + } + return require.resolve('jest-environment-jsdom'); +} + +module.exports = { getJestMajorVersion, getJestEnvironment }; diff --git a/packages/cli-module-test-jest/config/jest-environment-jsdom/index.js b/packages/cli-module-test-jest/config/jest-environment-jsdom/index.js new file mode 100644 index 0000000000..9d8b76eaf5 --- /dev/null +++ b/packages/cli-module-test-jest/config/jest-environment-jsdom/index.js @@ -0,0 +1,61 @@ +/* + * Copyright 2025 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. + */ + +const JSDOMEnvironment = require('@jest/environment-jsdom-abstract').default; +const jsdom = require('jsdom'); + +/** + * A custom JSDOM environment that extends the abstract base and applies + * fixes for Web API globals that are missing or incorrectly implemented + * in JSDOM. + * + * Based on https://github.com/mswjs/jest-fixed-jsdom + */ +class FixedJSDOMEnvironment extends JSDOMEnvironment { + constructor(config, context) { + super(config, context, jsdom); + + // Fix Web API globals that JSDOM doesn't properly expose + this.global.TextDecoder = TextDecoder; + this.global.TextEncoder = TextEncoder; + this.global.TextDecoderStream = TextDecoderStream; + this.global.TextEncoderStream = TextEncoderStream; + this.global.ReadableStream = ReadableStream; + + this.global.Blob = Blob; + this.global.Headers = Headers; + this.global.FormData = FormData; + this.global.Request = Request; + this.global.Response = Response; + this.global.fetch = fetch; + this.global.AbortController = AbortController; + this.global.AbortSignal = AbortSignal; + this.global.structuredClone = structuredClone; + this.global.URL = URL; + this.global.URLSearchParams = URLSearchParams; + + this.global.BroadcastChannel = BroadcastChannel; + this.global.TransformStream = TransformStream; + this.global.WritableStream = WritableStream; + + // Needed to ensure `e instanceof Error` works as expected with errors thrown from + // any of the native APIs above. Without this, the JSDOM `Error` is what the test + // code will use for comparison with `e`, which fails the instanceof check. + this.global.Error = Error; + } +} + +module.exports = FixedJSDOMEnvironment; diff --git a/packages/cli-module-test-jest/config/jest.js b/packages/cli-module-test-jest/config/jest.js new file mode 100644 index 0000000000..8a88483d42 --- /dev/null +++ b/packages/cli-module-test-jest/config/jest.js @@ -0,0 +1,422 @@ +/* + * Copyright 2020 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. + */ + +const fs = require('fs-extra'); +const path = require('node:path'); +const crypto = require('node:crypto'); +const glob = require('node:util').promisify(require('glob')); +const { version } = require('../package.json'); +const paths = require('@backstage/cli-common').findPaths(process.cwd()); +const { + getJestEnvironment, + getJestMajorVersion, +} = require('./getJestEnvironment'); + +const SRC_EXTS = ['ts', 'js', 'tsx', 'jsx', 'mts', 'cts', 'mjs', 'cjs']; + +const FRONTEND_ROLES = [ + 'frontend', + 'web-library', + 'common-library', + 'frontend-plugin', + 'frontend-plugin-module', +]; + +const NODE_ROLES = [ + 'backend', + 'cli', + 'cli-module', + 'node-library', + 'backend-plugin', + 'backend-plugin-module', +]; + +const envOptions = { + oldTests: Boolean(process.env.BACKSTAGE_OLD_TESTS), +}; + +try { + require.resolve('react-dom/client', { + paths: [paths.targetRoot], + }); + process.env.HAS_REACT_DOM_CLIENT = true; +} catch { + /* ignored */ +} + +/** + * A list of config keys that are valid for project-level config. + * Jest will complain if we forward any other root configuration to the projects. + * + * @type {Array} + */ +const projectConfigKeys = [ + 'automock', + 'cache', + 'cacheDirectory', + 'clearMocks', + 'collectCoverageFrom', + 'coverageDirectory', + 'coveragePathIgnorePatterns', + 'cwd', + 'dependencyExtractor', + 'detectLeaks', + 'detectOpenHandles', + 'displayName', + 'errorOnDeprecated', + 'extensionsToTreatAsEsm', + 'fakeTimers', + 'filter', + 'forceCoverageMatch', + 'globalSetup', + 'globalTeardown', + 'globals', + 'haste', + 'id', + 'injectGlobals', + 'moduleDirectories', + 'moduleFileExtensions', + 'moduleNameMapper', + 'modulePathIgnorePatterns', + 'modulePaths', + 'openHandlesTimeout', + 'preset', + 'prettierPath', + 'resetMocks', + 'resetModules', + 'resolver', + 'restoreMocks', + 'rootDir', + 'roots', + 'runner', + 'runtime', + 'sandboxInjectedGlobals', + 'setupFiles', + 'setupFilesAfterEnv', + 'skipFilter', + 'skipNodeResolution', + 'slowTestThreshold', + 'snapshotResolver', + 'snapshotSerializers', + 'snapshotFormat', + 'testEnvironment', + 'testEnvironmentOptions', + 'testMatch', + 'testLocationInResults', + 'testPathIgnorePatterns', + 'testRegex', + 'testRunner', + 'transform', + 'transformIgnorePatterns', + 'watchPathIgnorePatterns', + 'unmockedModulePathPatterns', + 'workerIdleMemoryLimit', +]; + +const transformIgnorePattern = [ + '@material-ui', + 'ajv', + 'core-js', + 'jest-.*', + 'jsdom', + 'knex', + 'react', + 'react-dom', + 'highlight\\.js', + 'prismjs', + 'json-schema', + 'react-use/lib', + 'typescript', +].join('|'); + +// Provides additional config that's based on the role of the target package +function getRoleConfig(role, pkgJson) { + // Only Node.js package roles support native ESM modules, frontend and common + // packages are always transpiled to CommonJS. + const moduleOpts = NODE_ROLES.includes(role) + ? { + module: { + ignoreDynamic: true, + exportInteropAnnotation: true, + }, + } + : undefined; + + const transform = { + '\\.(mjs|cjs|js)$': [ + require.resolve('./jestSwcTransform'), + { + ...moduleOpts, + jsc: { + parser: { + syntax: 'ecmascript', + }, + }, + }, + ], + '\\.jsx$': [ + require.resolve('./jestSwcTransform'), + { + jsc: { + parser: { + syntax: 'ecmascript', + jsx: true, + }, + transform: { + react: { + runtime: 'automatic', + }, + }, + }, + }, + ], + '\\.(mts|cts|ts)$': [ + require.resolve('./jestSwcTransform'), + { + ...moduleOpts, + jsc: { + parser: { + syntax: 'typescript', + }, + }, + }, + ], + '\\.tsx$': [ + require.resolve('./jestSwcTransform'), + { + jsc: { + parser: { + syntax: 'typescript', + tsx: true, + }, + transform: { + react: { + runtime: 'automatic', + }, + }, + }, + }, + ], + '\\.(bmp|gif|jpg|jpeg|png|ico|webp|frag|xml|svg|eot|woff|woff2|ttf)$': + require.resolve('./jestFileTransform.js'), + '\\.(yaml)$': require.resolve('./jestYamlTransform'), + }; + if (FRONTEND_ROLES.includes(role)) { + return { + testEnvironment: getJestEnvironment(), + // The caching module loader is only used to speed up frontend tests, + // as it breaks real dynamic imports of ESM modules. + runtime: envOptions.oldTests + ? undefined + : require.resolve('./jestCachingModuleLoader'), + transform, + }; + } + return { + testEnvironment: require.resolve('jest-environment-node'), + moduleFileExtensions: [...SRC_EXTS, 'json', 'node'], + // Jest doesn't let us dynamically detect type=module per transformed file, + // so we have to assume that if the entry point is ESM, all TS files are + // ESM. + // + // This means you can't switch a package to type=module until all of its + // monorepo dependencies are also type=module or does not contain any .ts + // files. + extensionsToTreatAsEsm: + pkgJson.type === 'module' ? ['.ts', '.mts'] : ['.mts'], + transform, + }; +} + +async function getProjectConfig(targetPath, extraConfig, extraOptions) { + const configJsPath = path.resolve(targetPath, 'jest.config.js'); + const configTsPath = path.resolve(targetPath, 'jest.config.ts'); + // If the package has it's own jest config, we use that instead. + if (await fs.pathExists(configJsPath)) { + return require(configJsPath); + } else if (await fs.pathExists(configTsPath)) { + return require(configTsPath); + } + + // Jest config can be defined both in the root package.json and within each package. The root config + // gets forwarded to us through the `extraConfig` parameter, while the package config is read here. + // If they happen to be the same the keys will simply override each other. + // The merging of the configs is shallow, meaning e.g. all transforms are replaced if new ones are defined. + const pkgJson = await fs.readJson(path.resolve(targetPath, 'package.json')); + + const options = { + ...extraConfig, + rootDir: path.resolve(targetPath, 'src'), + moduleNameMapper: { + '\\.(css|less|scss|sss|styl)$': require.resolve('jest-css-modules'), + }, + + // A bit more opinionated + testMatch: [`**/*.test.{${SRC_EXTS.join(',')}}`], + + transformIgnorePatterns: [`/node_modules/(?:${transformIgnorePattern})/`], + ...getRoleConfig(pkgJson.backstage?.role, pkgJson), + }; + + options.setupFilesAfterEnv = options.setupFilesAfterEnv || []; + + if ( + extraOptions.rejectFrontendNetworkRequests && + FRONTEND_ROLES.includes(pkgJson.backstage?.role) + ) { + // By adding this first we ensure that it's possible to for example override + // fetch with a mock in a custom setup file + options.setupFilesAfterEnv.unshift( + require.resolve('./jestRejectNetworkRequests.js'), + ); + } + + if ( + options.testEnvironment === getJestEnvironment() && + getJestMajorVersion() < 30 // Only needed when not running the custom env for Jest 30+ + ) { + // FIXME https://github.com/jsdom/jsdom/issues/1724 + options.setupFilesAfterEnv.unshift(require.resolve('cross-fetch/polyfill')); + } + + // Use src/setupTests.* as the default location for configuring test env + for (const ext of SRC_EXTS) { + if (fs.existsSync(path.resolve(targetPath, `src/setupTests.${ext}`))) { + options.setupFilesAfterEnv.push(`/setupTests.${ext}`); + break; + } + } + + const config = Object.assign(options, pkgJson.jest); + + // The config id is a cache key that lets us share the jest cache across projects. + // If no explicit id was configured, generated one based on the configuration. + if (!config.id) { + const configHash = crypto + .createHash('sha256') + .update(version) + .update(Buffer.alloc(1)) + .update(JSON.stringify(config.transform).replaceAll(paths.targetRoot, '')) + .digest('hex'); + config.id = `backstage_cli_${configHash}`; + } + + return config; +} + +// This loads the root jest config, which in turn will either refer to a single +// configuration for the current package, or a collection of configurations for +// the target workspace packages +async function getRootConfig() { + const rootPkgJson = await fs.readJson( + paths.resolveTargetRoot('package.json'), + ); + + const baseCoverageConfig = { + coverageDirectory: paths.resolveTarget('coverage'), + coverageProvider: envOptions.oldTests ? 'v8' : 'babel', + collectCoverageFrom: ['**/*.{js,jsx,ts,tsx,mjs,cjs}', '!**/*.d.ts'], + }; + + const { rejectFrontendNetworkRequests, ...rootOptions } = + rootPkgJson.jest ?? {}; + const extraRootOptions = { + rejectFrontendNetworkRequests, + }; + + const ws = rootPkgJson.workspaces; + const workspacePatterns = Array.isArray(ws) ? ws : ws?.packages; + + // Check if we're running within a specific monorepo package. In that case just get the single project config. + if (!workspacePatterns || paths.targetRoot !== paths.targetDir) { + return getProjectConfig( + paths.targetDir, + { + ...baseCoverageConfig, + ...rootOptions, + }, + extraRootOptions, + ); + } + + const globalRootConfig = { ...baseCoverageConfig }; + const globalProjectConfig = {}; + + for (const [key, value] of Object.entries(rootOptions)) { + if (projectConfigKeys.includes(key)) { + globalProjectConfig[key] = value; + } else { + globalRootConfig[key] = value; + } + } + + // If the target package is a workspace root, we find all packages in the + // workspace and load those in as separate jest projects instead. + const projectPaths = await Promise.all( + workspacePatterns.map(pattern => + glob(path.join(paths.targetRoot, pattern)), + ), + ).then(_ => _.flat()); + + let projects = await Promise.all( + projectPaths.flat().map(async projectPath => { + const packagePath = path.resolve(projectPath, 'package.json'); + if (!(await fs.pathExists(packagePath))) { + return undefined; + } + + // We check for the presence of "backstage-cli test" in the package test + // script to determine whether a given package should be tested + const packageData = await fs.readJson(packagePath); + const testScript = packageData.scripts && packageData.scripts.test; + const isSupportedTestScript = + testScript?.includes('backstage-cli test') || + testScript?.includes('backstage-cli package test'); + if (testScript && isSupportedTestScript) { + return await getProjectConfig( + projectPath, + { + ...globalProjectConfig, + displayName: packageData.name, + }, + extraRootOptions, + ); + } + + return undefined; + }), + ).then(cs => cs.filter(Boolean)); + + const cache = global.__backstageCli_jestSuccessCache; + if (cache) { + projects = await cache.filterConfigs(projects, globalRootConfig); + } + const watchProjectFilter = global.__backstageCli_watchProjectFilter; + if (watchProjectFilter) { + projects = await watchProjectFilter.filter(projects); + } + + return { + rootDir: paths.targetRoot, + projects, + testResultsProcessor: cache + ? require.resolve('./jestCacheResultProcessor.cjs') + : undefined, + ...globalRootConfig, + }; +} + +module.exports = getRootConfig(); diff --git a/packages/cli-module-test-jest/config/jestCacheResultProcessor.cjs b/packages/cli-module-test-jest/config/jestCacheResultProcessor.cjs new file mode 100644 index 0000000000..4af401d8b5 --- /dev/null +++ b/packages/cli-module-test-jest/config/jestCacheResultProcessor.cjs @@ -0,0 +1,23 @@ +/* + * 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. + */ + +module.exports = async results => { + const cache = global.__backstageCli_jestSuccessCache; + if (cache) { + await cache.reportResults(results); + } + return results; +}; diff --git a/packages/cli-module-test-jest/config/jestCachingModuleLoader.js b/packages/cli-module-test-jest/config/jestCachingModuleLoader.js new file mode 100644 index 0000000000..5652ff67e7 --- /dev/null +++ b/packages/cli-module-test-jest/config/jestCachingModuleLoader.js @@ -0,0 +1,35 @@ +/* + * Copyright 2022 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. + */ + +// 'jest-runtime' is included with jest and should be kept in sync with the installed jest version +// eslint-disable-next-line @backstage/no-undeclared-imports +const { default: JestRuntime } = require('jest-runtime'); + +module.exports = class CachingJestRuntime extends JestRuntime { + constructor(config, ...restArgs) { + super(config, ...restArgs); + this.allowLoadAsEsm = config.extensionsToTreatAsEsm.includes('.mts'); + } + + // Unfortunately we need to use this unstable API to make sure that .js files + // are only loaded as modules where ESM is supported, i.e. Node.js packages. + unstable_shouldLoadAsEsm(path, ...restArgs) { + if (!this.allowLoadAsEsm) { + return false; + } + return super.unstable_shouldLoadAsEsm(path, ...restArgs); + } +}; diff --git a/packages/cli-module-test-jest/config/jestFileTransform.js b/packages/cli-module-test-jest/config/jestFileTransform.js new file mode 100644 index 0000000000..ad1c37a4f5 --- /dev/null +++ b/packages/cli-module-test-jest/config/jestFileTransform.js @@ -0,0 +1,44 @@ +/* + * Copyright 2020 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. + */ + +const path = require('node:path'); + +module.exports = { + process(src, filename) { + const assetFilename = JSON.stringify(path.basename(filename)); + + if (filename.match(/\.icon\.svg$/)) { + return { + code: `const React = require('react'); + const SvgIcon = require('@material-ui/core/SvgIcon').default; + module.exports = { + __esModule: true, + default: props => React.createElement(SvgIcon, props, { + $$typeof: Symbol.for('react.element'), + type: 'svg', + ref: ref, + key: null, + props: Object.assign({}, props, { + children: ${assetFilename} + }) + }) + };`, + }; + } + + return { code: `module.exports = ${assetFilename};` }; + }, +}; diff --git a/packages/cli-module-test-jest/config/jestRejectNetworkRequests.js b/packages/cli-module-test-jest/config/jestRejectNetworkRequests.js new file mode 100644 index 0000000000..f6f189a60c --- /dev/null +++ b/packages/cli-module-test-jest/config/jestRejectNetworkRequests.js @@ -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. + */ + +const http = require('node:http'); +const https = require('node:https'); + +const errorMessage = 'Network requests are not allowed in tests'; + +const origHttpAgent = http.globalAgent; +const origHttpsAgent = https.globalAgent; +const origFetch = global.fetch; +const origXMLHttpRequest = global.XMLHttpRequest; + +http.globalAgent = new http.Agent({ + lookup() { + throw new Error(errorMessage); + }, +}); + +https.globalAgent = new https.Agent({ + lookup() { + throw new Error(errorMessage); + }, +}); + +const BLOCKING_FETCH_SYMBOL = Symbol.for( + 'backstage.jestRejectNetworkRequests.blockingFetch', +); + +if (global.fetch) { + const blockingFetch = async (input, init) => { + // If global.fetch still has our marker, block the request + if (global.fetch[BLOCKING_FETCH_SYMBOL]) { + throw new Error(errorMessage); + } + // MSW (or something else) wrapped us - pass through + return origFetch(input, init); + }; + blockingFetch[BLOCKING_FETCH_SYMBOL] = true; + global.fetch = blockingFetch; +} + +if (global.XMLHttpRequest) { + global.XMLHttpRequest = class { + constructor() { + throw new Error(errorMessage); + } + }; +} + +// Reset overrides after each suite to make sure we don't pollute the test environment +afterAll(() => { + http.globalAgent = origHttpAgent; + https.globalAgent = origHttpsAgent; + global.fetch = origFetch; + global.XMLHttpRequest = origXMLHttpRequest; +}); diff --git a/packages/cli-module-test-jest/config/jestSucraseTransform.js b/packages/cli-module-test-jest/config/jestSucraseTransform.js new file mode 100644 index 0000000000..621b9ee297 --- /dev/null +++ b/packages/cli-module-test-jest/config/jestSucraseTransform.js @@ -0,0 +1,87 @@ +/* + * Copyright 2021 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. + */ + +const { createHash } = require('node:crypto'); +const { transform } = require('sucrase'); +const sucrasePkg = require('sucrase/package.json'); + +const ESM_REGEX = /\b(?:import|export)\b/; + +function createTransformer(config) { + const process = (source, filePath) => { + let transforms; + + if (filePath.endsWith('.esm.js')) { + transforms = ['imports']; + } else if (filePath.endsWith('.js')) { + // This is a very rough filter to avoid transforming things that we quickly + // can be sure are definitely not ESM modules. + if (ESM_REGEX.test(source)) { + transforms = ['imports', 'jsx']; // JSX within .js is currently allowed + } + } else if (filePath.endsWith('.jsx')) { + transforms = ['jsx', 'imports']; + } else if (filePath.endsWith('.ts')) { + transforms = ['typescript', 'imports']; + } else if (filePath.endsWith('.tsx')) { + transforms = ['typescript', 'jsx', 'imports']; + } + + // Only apply the jest transform to the test files themselves + if (transforms && filePath.includes('.test.')) { + transforms.push('jest'); + } + + if (transforms) { + const { code, sourceMap: map } = transform(source, { + transforms, + filePath, + disableESTransforms: true, + sourceMapOptions: { + compiledFilename: filePath, + }, + }); + if (config.enableSourceMaps) { + const b64 = Buffer.from(JSON.stringify(map), 'utf8').toString('base64'); + const suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${b64}`; + // Include both inline and object source maps, as inline source maps are + // needed for support of some editor integrations. + return { code: `${code}\n${suffix}`, map }; + } + // We only return the `map` result if source maps are enabled, as they + // have a negative impact on the coverage accuracy. + return { code }; + } + + return { code: source }; + }; + + const getCacheKey = sourceText => { + return createHash('sha256') + .update(sourceText) + .update(Buffer.alloc(1)) + .update(sucrasePkg.version) + .update(Buffer.alloc(1)) + .update(JSON.stringify(config)) + .update(Buffer.alloc(1)) + .update('1') // increment whenever the transform logic in this file changes + .digest('hex'); + }; + + return { process, getCacheKey }; +} + +module.exports = { createTransformer }; diff --git a/packages/cli-module-test-jest/config/jestSwcTransform.js b/packages/cli-module-test-jest/config/jestSwcTransform.js new file mode 100644 index 0000000000..4183349554 --- /dev/null +++ b/packages/cli-module-test-jest/config/jestSwcTransform.js @@ -0,0 +1,44 @@ +/* + * Copyright 2022 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. + */ +const { createTransformer: createSwcTransformer } = require('@swc/jest'); + +const ESM_REGEX = /\b(?:import|export)\b/; + +function createTransformer(config) { + const swcTransformer = createSwcTransformer({ + inputSourceMap: false, + ...config, + }); + const process = (source, filePath, jestOptions) => { + // Skip transformation of .js files without ESM syntax, we never transform from CJS to ESM + if (filePath.endsWith('.js') && !ESM_REGEX.test(source)) { + return { code: source }; + } + + // Skip transformation of .mjs files, they should only be used if ESM support is available + if (jestOptions.supportsStaticESM && filePath.endsWith('.mjs')) { + return { code: source }; + } + + return swcTransformer.process(source, filePath, jestOptions); + }; + + const getCacheKey = swcTransformer.getCacheKey; + + return { process, getCacheKey }; +} + +module.exports = { createTransformer }; diff --git a/packages/cli-module-test-jest/config/jestYamlTransform.js b/packages/cli-module-test-jest/config/jestYamlTransform.js new file mode 100644 index 0000000000..7a05274add --- /dev/null +++ b/packages/cli-module-test-jest/config/jestYamlTransform.js @@ -0,0 +1,40 @@ +/* + * Copyright 2022 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. + */ + +const yaml = require('yaml'); +const crypto = require('node:crypto'); + +function createTransformer(config) { + const process = source => { + const json = JSON.stringify(yaml.parse(source), null, 2); + return { code: `module.exports = ${json}`, map: null }; + }; + + const getCacheKey = sourceText => { + return crypto + .createHash('sha256') + .update(sourceText) + .update(Buffer.alloc(1)) + .update(JSON.stringify(config)) + .update(Buffer.alloc(1)) + .update('1') // increment whenever the transform logic in this file changes + .digest('hex'); + }; + + return { process, getCacheKey }; +} + +module.exports = { createTransformer }; diff --git a/packages/cli-module-test-jest/package.json b/packages/cli-module-test-jest/package.json index b02167a934..f83558327c 100644 --- a/packages/cli-module-test-jest/package.json +++ b/packages/cli-module-test-jest/package.json @@ -21,7 +21,8 @@ "types": "src/index.ts", "files": [ "dist", - "bin" + "bin", + "config" ], "scripts": { "build": "backstage-cli package build", @@ -34,14 +35,35 @@ "dependencies": { "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^", + "@swc/core": "^1.15.6", + "@swc/jest": "^0.2.39", "cleye": "^2.3.0", + "cross-fetch": "^4.0.0", + "fs-extra": "^11.2.0", + "glob": "^7.1.7", + "jest-css-modules": "^2.1.0", + "sucrase": "^3.20.2", "yargs": "^16.2.0" }, "devDependencies": { "@backstage/cli": "workspace:^" }, "peerDependencies": { - "jest-cli": "^29.0.0 || ^30.0.0" + "@jest/environment-jsdom-abstract": "^30.0.0", + "jest-cli": "^29.0.0 || ^30.0.0", + "jest-environment-jsdom": "*", + "jsdom": "^27.1.0" + }, + "peerDependenciesMeta": { + "@jest/environment-jsdom-abstract": { + "optional": true + }, + "jest-environment-jsdom": { + "optional": true + }, + "jsdom": { + "optional": true + } }, "bin": "bin/cli-module-test-jest" } diff --git a/packages/cli-module-test-jest/src/commands/package/test.ts b/packages/cli-module-test-jest/src/commands/package/test.ts index 6c9ad50e5b..b260601f8e 100644 --- a/packages/cli-module-test-jest/src/commands/package/test.ts +++ b/packages/cli-module-test-jest/src/commands/package/test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { runCheck } from '@backstage/cli-common'; +import { findOwnPaths, runCheck } from '@backstage/cli-common'; import type { CliCommandContext } from '@backstage/cli-node'; function includesAnyOf(hayStack: string[], ...needles: string[]) { @@ -30,7 +30,7 @@ export default async ({ args }: CliCommandContext) => { // Only include our config if caller isn't passing their own config if (!includesAnyOf(args, '-c', '--config')) { /* eslint-disable-next-line no-restricted-syntax */ - args.push('--config', require.resolve('@backstage/cli/config/jest')); + args.push('--config', findOwnPaths(__dirname).resolve('config/jest.js')); } if (!includesAnyOf(args, '--no-passWithNoTests', '--passWithNoTests=false')) { diff --git a/packages/cli-module-test-jest/src/commands/repo/test.ts b/packages/cli-module-test-jest/src/commands/repo/test.ts index e45df2bcfc..806d88965b 100644 --- a/packages/cli-module-test-jest/src/commands/repo/test.ts +++ b/packages/cli-module-test-jest/src/commands/repo/test.ts @@ -25,6 +25,7 @@ import { relative as relativePath } from 'node:path'; import { Lockfile, PackageGraph, SuccessCache } from '@backstage/cli-node'; import { + findOwnPaths, runCheck, runOutput, targetPaths, @@ -181,7 +182,7 @@ export default async ({ args, info }: CliCommandContext) => { // Only include our config if caller isn't passing their own config if (!hasFlags('-c', '--config')) { /* eslint-disable-next-line no-restricted-syntax */ - args.push('--config', require.resolve('@backstage/cli/config/jest')); + args.push('--config', findOwnPaths(__dirname).resolve('config/jest.js')); } if (!hasFlags('--passWithNoTests')) { diff --git a/packages/cli/config/getJestEnvironment.js b/packages/cli/config/getJestEnvironment.js index aac2f79021..e6fb66f407 100644 --- a/packages/cli/config/getJestEnvironment.js +++ b/packages/cli/config/getJestEnvironment.js @@ -14,36 +14,14 @@ * limitations under the License. */ -function getJestMajorVersion() { - const jestVersion = require('jest/package.json').version; - const majorVersion = parseInt(jestVersion.split('.')[0], 10); - return majorVersion; -} - -function getJestEnvironment() { - const majorVersion = getJestMajorVersion(); - - if (majorVersion >= 30) { - try { - require.resolve('@jest/environment-jsdom-abstract'); - require.resolve('jsdom'); - } catch { - throw new Error( - 'Jest 30+ requires @jest/environment-jsdom-abstract and jsdom. ' + - 'Please install them as dev dependencies.', - ); - } - return require.resolve('./jest-environment-jsdom'); - } - try { - require.resolve('jest-environment-jsdom'); - } catch { +try { + module.exports = require('@backstage/cli-module-test-jest/config/getJestEnvironment'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { throw new Error( - 'Jest 29 requires jest-environment-jsdom. ' + - 'Please install it as a dev dependency.', + '@backstage/cli-module-test-jest is required to use the jest environment configuration. ' + + 'Please install it as a dependency.', ); } - return require.resolve('jest-environment-jsdom'); + throw e; } - -module.exports = { getJestMajorVersion, getJestEnvironment }; diff --git a/packages/cli/config/jest-environment-jsdom/index.js b/packages/cli/config/jest-environment-jsdom/index.js index 9d8b76eaf5..f9be215d76 100644 --- a/packages/cli/config/jest-environment-jsdom/index.js +++ b/packages/cli/config/jest-environment-jsdom/index.js @@ -14,48 +14,14 @@ * limitations under the License. */ -const JSDOMEnvironment = require('@jest/environment-jsdom-abstract').default; -const jsdom = require('jsdom'); - -/** - * A custom JSDOM environment that extends the abstract base and applies - * fixes for Web API globals that are missing or incorrectly implemented - * in JSDOM. - * - * Based on https://github.com/mswjs/jest-fixed-jsdom - */ -class FixedJSDOMEnvironment extends JSDOMEnvironment { - constructor(config, context) { - super(config, context, jsdom); - - // Fix Web API globals that JSDOM doesn't properly expose - this.global.TextDecoder = TextDecoder; - this.global.TextEncoder = TextEncoder; - this.global.TextDecoderStream = TextDecoderStream; - this.global.TextEncoderStream = TextEncoderStream; - this.global.ReadableStream = ReadableStream; - - this.global.Blob = Blob; - this.global.Headers = Headers; - this.global.FormData = FormData; - this.global.Request = Request; - this.global.Response = Response; - this.global.fetch = fetch; - this.global.AbortController = AbortController; - this.global.AbortSignal = AbortSignal; - this.global.structuredClone = structuredClone; - this.global.URL = URL; - this.global.URLSearchParams = URLSearchParams; - - this.global.BroadcastChannel = BroadcastChannel; - this.global.TransformStream = TransformStream; - this.global.WritableStream = WritableStream; - - // Needed to ensure `e instanceof Error` works as expected with errors thrown from - // any of the native APIs above. Without this, the JSDOM `Error` is what the test - // code will use for comparison with `e`, which fails the instanceof check. - this.global.Error = Error; +try { + module.exports = require('@backstage/cli-module-test-jest/config/jest-environment-jsdom'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-test-jest is required to use the jest JSDOM environment. ' + + 'Please install it as a dependency.', + ); } + throw e; } - -module.exports = FixedJSDOMEnvironment; diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js index 8a88483d42..e06d0e319e 100644 --- a/packages/cli/config/jest.js +++ b/packages/cli/config/jest.js @@ -14,409 +14,14 @@ * limitations under the License. */ -const fs = require('fs-extra'); -const path = require('node:path'); -const crypto = require('node:crypto'); -const glob = require('node:util').promisify(require('glob')); -const { version } = require('../package.json'); -const paths = require('@backstage/cli-common').findPaths(process.cwd()); -const { - getJestEnvironment, - getJestMajorVersion, -} = require('./getJestEnvironment'); - -const SRC_EXTS = ['ts', 'js', 'tsx', 'jsx', 'mts', 'cts', 'mjs', 'cjs']; - -const FRONTEND_ROLES = [ - 'frontend', - 'web-library', - 'common-library', - 'frontend-plugin', - 'frontend-plugin-module', -]; - -const NODE_ROLES = [ - 'backend', - 'cli', - 'cli-module', - 'node-library', - 'backend-plugin', - 'backend-plugin-module', -]; - -const envOptions = { - oldTests: Boolean(process.env.BACKSTAGE_OLD_TESTS), -}; - try { - require.resolve('react-dom/client', { - paths: [paths.targetRoot], - }); - process.env.HAS_REACT_DOM_CLIENT = true; -} catch { - /* ignored */ -} - -/** - * A list of config keys that are valid for project-level config. - * Jest will complain if we forward any other root configuration to the projects. - * - * @type {Array} - */ -const projectConfigKeys = [ - 'automock', - 'cache', - 'cacheDirectory', - 'clearMocks', - 'collectCoverageFrom', - 'coverageDirectory', - 'coveragePathIgnorePatterns', - 'cwd', - 'dependencyExtractor', - 'detectLeaks', - 'detectOpenHandles', - 'displayName', - 'errorOnDeprecated', - 'extensionsToTreatAsEsm', - 'fakeTimers', - 'filter', - 'forceCoverageMatch', - 'globalSetup', - 'globalTeardown', - 'globals', - 'haste', - 'id', - 'injectGlobals', - 'moduleDirectories', - 'moduleFileExtensions', - 'moduleNameMapper', - 'modulePathIgnorePatterns', - 'modulePaths', - 'openHandlesTimeout', - 'preset', - 'prettierPath', - 'resetMocks', - 'resetModules', - 'resolver', - 'restoreMocks', - 'rootDir', - 'roots', - 'runner', - 'runtime', - 'sandboxInjectedGlobals', - 'setupFiles', - 'setupFilesAfterEnv', - 'skipFilter', - 'skipNodeResolution', - 'slowTestThreshold', - 'snapshotResolver', - 'snapshotSerializers', - 'snapshotFormat', - 'testEnvironment', - 'testEnvironmentOptions', - 'testMatch', - 'testLocationInResults', - 'testPathIgnorePatterns', - 'testRegex', - 'testRunner', - 'transform', - 'transformIgnorePatterns', - 'watchPathIgnorePatterns', - 'unmockedModulePathPatterns', - 'workerIdleMemoryLimit', -]; - -const transformIgnorePattern = [ - '@material-ui', - 'ajv', - 'core-js', - 'jest-.*', - 'jsdom', - 'knex', - 'react', - 'react-dom', - 'highlight\\.js', - 'prismjs', - 'json-schema', - 'react-use/lib', - 'typescript', -].join('|'); - -// Provides additional config that's based on the role of the target package -function getRoleConfig(role, pkgJson) { - // Only Node.js package roles support native ESM modules, frontend and common - // packages are always transpiled to CommonJS. - const moduleOpts = NODE_ROLES.includes(role) - ? { - module: { - ignoreDynamic: true, - exportInteropAnnotation: true, - }, - } - : undefined; - - const transform = { - '\\.(mjs|cjs|js)$': [ - require.resolve('./jestSwcTransform'), - { - ...moduleOpts, - jsc: { - parser: { - syntax: 'ecmascript', - }, - }, - }, - ], - '\\.jsx$': [ - require.resolve('./jestSwcTransform'), - { - jsc: { - parser: { - syntax: 'ecmascript', - jsx: true, - }, - transform: { - react: { - runtime: 'automatic', - }, - }, - }, - }, - ], - '\\.(mts|cts|ts)$': [ - require.resolve('./jestSwcTransform'), - { - ...moduleOpts, - jsc: { - parser: { - syntax: 'typescript', - }, - }, - }, - ], - '\\.tsx$': [ - require.resolve('./jestSwcTransform'), - { - jsc: { - parser: { - syntax: 'typescript', - tsx: true, - }, - transform: { - react: { - runtime: 'automatic', - }, - }, - }, - }, - ], - '\\.(bmp|gif|jpg|jpeg|png|ico|webp|frag|xml|svg|eot|woff|woff2|ttf)$': - require.resolve('./jestFileTransform.js'), - '\\.(yaml)$': require.resolve('./jestYamlTransform'), - }; - if (FRONTEND_ROLES.includes(role)) { - return { - testEnvironment: getJestEnvironment(), - // The caching module loader is only used to speed up frontend tests, - // as it breaks real dynamic imports of ESM modules. - runtime: envOptions.oldTests - ? undefined - : require.resolve('./jestCachingModuleLoader'), - transform, - }; - } - return { - testEnvironment: require.resolve('jest-environment-node'), - moduleFileExtensions: [...SRC_EXTS, 'json', 'node'], - // Jest doesn't let us dynamically detect type=module per transformed file, - // so we have to assume that if the entry point is ESM, all TS files are - // ESM. - // - // This means you can't switch a package to type=module until all of its - // monorepo dependencies are also type=module or does not contain any .ts - // files. - extensionsToTreatAsEsm: - pkgJson.type === 'module' ? ['.ts', '.mts'] : ['.mts'], - transform, - }; -} - -async function getProjectConfig(targetPath, extraConfig, extraOptions) { - const configJsPath = path.resolve(targetPath, 'jest.config.js'); - const configTsPath = path.resolve(targetPath, 'jest.config.ts'); - // If the package has it's own jest config, we use that instead. - if (await fs.pathExists(configJsPath)) { - return require(configJsPath); - } else if (await fs.pathExists(configTsPath)) { - return require(configTsPath); - } - - // Jest config can be defined both in the root package.json and within each package. The root config - // gets forwarded to us through the `extraConfig` parameter, while the package config is read here. - // If they happen to be the same the keys will simply override each other. - // The merging of the configs is shallow, meaning e.g. all transforms are replaced if new ones are defined. - const pkgJson = await fs.readJson(path.resolve(targetPath, 'package.json')); - - const options = { - ...extraConfig, - rootDir: path.resolve(targetPath, 'src'), - moduleNameMapper: { - '\\.(css|less|scss|sss|styl)$': require.resolve('jest-css-modules'), - }, - - // A bit more opinionated - testMatch: [`**/*.test.{${SRC_EXTS.join(',')}}`], - - transformIgnorePatterns: [`/node_modules/(?:${transformIgnorePattern})/`], - ...getRoleConfig(pkgJson.backstage?.role, pkgJson), - }; - - options.setupFilesAfterEnv = options.setupFilesAfterEnv || []; - - if ( - extraOptions.rejectFrontendNetworkRequests && - FRONTEND_ROLES.includes(pkgJson.backstage?.role) - ) { - // By adding this first we ensure that it's possible to for example override - // fetch with a mock in a custom setup file - options.setupFilesAfterEnv.unshift( - require.resolve('./jestRejectNetworkRequests.js'), + module.exports = require('@backstage/cli-module-test-jest/config/jest'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-test-jest is required to use this jest configuration. ' + + 'Please install it as a dependency.', ); } - - if ( - options.testEnvironment === getJestEnvironment() && - getJestMajorVersion() < 30 // Only needed when not running the custom env for Jest 30+ - ) { - // FIXME https://github.com/jsdom/jsdom/issues/1724 - options.setupFilesAfterEnv.unshift(require.resolve('cross-fetch/polyfill')); - } - - // Use src/setupTests.* as the default location for configuring test env - for (const ext of SRC_EXTS) { - if (fs.existsSync(path.resolve(targetPath, `src/setupTests.${ext}`))) { - options.setupFilesAfterEnv.push(`/setupTests.${ext}`); - break; - } - } - - const config = Object.assign(options, pkgJson.jest); - - // The config id is a cache key that lets us share the jest cache across projects. - // If no explicit id was configured, generated one based on the configuration. - if (!config.id) { - const configHash = crypto - .createHash('sha256') - .update(version) - .update(Buffer.alloc(1)) - .update(JSON.stringify(config.transform).replaceAll(paths.targetRoot, '')) - .digest('hex'); - config.id = `backstage_cli_${configHash}`; - } - - return config; + throw e; } - -// This loads the root jest config, which in turn will either refer to a single -// configuration for the current package, or a collection of configurations for -// the target workspace packages -async function getRootConfig() { - const rootPkgJson = await fs.readJson( - paths.resolveTargetRoot('package.json'), - ); - - const baseCoverageConfig = { - coverageDirectory: paths.resolveTarget('coverage'), - coverageProvider: envOptions.oldTests ? 'v8' : 'babel', - collectCoverageFrom: ['**/*.{js,jsx,ts,tsx,mjs,cjs}', '!**/*.d.ts'], - }; - - const { rejectFrontendNetworkRequests, ...rootOptions } = - rootPkgJson.jest ?? {}; - const extraRootOptions = { - rejectFrontendNetworkRequests, - }; - - const ws = rootPkgJson.workspaces; - const workspacePatterns = Array.isArray(ws) ? ws : ws?.packages; - - // Check if we're running within a specific monorepo package. In that case just get the single project config. - if (!workspacePatterns || paths.targetRoot !== paths.targetDir) { - return getProjectConfig( - paths.targetDir, - { - ...baseCoverageConfig, - ...rootOptions, - }, - extraRootOptions, - ); - } - - const globalRootConfig = { ...baseCoverageConfig }; - const globalProjectConfig = {}; - - for (const [key, value] of Object.entries(rootOptions)) { - if (projectConfigKeys.includes(key)) { - globalProjectConfig[key] = value; - } else { - globalRootConfig[key] = value; - } - } - - // If the target package is a workspace root, we find all packages in the - // workspace and load those in as separate jest projects instead. - const projectPaths = await Promise.all( - workspacePatterns.map(pattern => - glob(path.join(paths.targetRoot, pattern)), - ), - ).then(_ => _.flat()); - - let projects = await Promise.all( - projectPaths.flat().map(async projectPath => { - const packagePath = path.resolve(projectPath, 'package.json'); - if (!(await fs.pathExists(packagePath))) { - return undefined; - } - - // We check for the presence of "backstage-cli test" in the package test - // script to determine whether a given package should be tested - const packageData = await fs.readJson(packagePath); - const testScript = packageData.scripts && packageData.scripts.test; - const isSupportedTestScript = - testScript?.includes('backstage-cli test') || - testScript?.includes('backstage-cli package test'); - if (testScript && isSupportedTestScript) { - return await getProjectConfig( - projectPath, - { - ...globalProjectConfig, - displayName: packageData.name, - }, - extraRootOptions, - ); - } - - return undefined; - }), - ).then(cs => cs.filter(Boolean)); - - const cache = global.__backstageCli_jestSuccessCache; - if (cache) { - projects = await cache.filterConfigs(projects, globalRootConfig); - } - const watchProjectFilter = global.__backstageCli_watchProjectFilter; - if (watchProjectFilter) { - projects = await watchProjectFilter.filter(projects); - } - - return { - rootDir: paths.targetRoot, - projects, - testResultsProcessor: cache - ? require.resolve('./jestCacheResultProcessor.cjs') - : undefined, - ...globalRootConfig, - }; -} - -module.exports = getRootConfig(); diff --git a/packages/cli/config/jestCacheResultProcessor.cjs b/packages/cli/config/jestCacheResultProcessor.cjs index 4af401d8b5..58217428cc 100644 --- a/packages/cli/config/jestCacheResultProcessor.cjs +++ b/packages/cli/config/jestCacheResultProcessor.cjs @@ -14,10 +14,14 @@ * limitations under the License. */ -module.exports = async results => { - const cache = global.__backstageCli_jestSuccessCache; - if (cache) { - await cache.reportResults(results); +try { + module.exports = require('@backstage/cli-module-test-jest/config/jestCacheResultProcessor.cjs'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-test-jest is required to use the jest cache result processor. ' + + 'Please install it as a dependency.', + ); } - return results; -}; + throw e; +} diff --git a/packages/cli/config/jestCachingModuleLoader.js b/packages/cli/config/jestCachingModuleLoader.js index 5652ff67e7..2b6da11007 100644 --- a/packages/cli/config/jestCachingModuleLoader.js +++ b/packages/cli/config/jestCachingModuleLoader.js @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2023 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. @@ -14,22 +14,14 @@ * limitations under the License. */ -// 'jest-runtime' is included with jest and should be kept in sync with the installed jest version -// eslint-disable-next-line @backstage/no-undeclared-imports -const { default: JestRuntime } = require('jest-runtime'); - -module.exports = class CachingJestRuntime extends JestRuntime { - constructor(config, ...restArgs) { - super(config, ...restArgs); - this.allowLoadAsEsm = config.extensionsToTreatAsEsm.includes('.mts'); +try { + module.exports = require('@backstage/cli-module-test-jest/config/jestCachingModuleLoader'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-test-jest is required to use the jest caching module loader. ' + + 'Please install it as a dependency.', + ); } - - // Unfortunately we need to use this unstable API to make sure that .js files - // are only loaded as modules where ESM is supported, i.e. Node.js packages. - unstable_shouldLoadAsEsm(path, ...restArgs) { - if (!this.allowLoadAsEsm) { - return false; - } - return super.unstable_shouldLoadAsEsm(path, ...restArgs); - } -}; + throw e; +} diff --git a/packages/cli/config/jestFileTransform.js b/packages/cli/config/jestFileTransform.js index ad1c37a4f5..00e1c22815 100644 --- a/packages/cli/config/jestFileTransform.js +++ b/packages/cli/config/jestFileTransform.js @@ -14,31 +14,14 @@ * limitations under the License. */ -const path = require('node:path'); - -module.exports = { - process(src, filename) { - const assetFilename = JSON.stringify(path.basename(filename)); - - if (filename.match(/\.icon\.svg$/)) { - return { - code: `const React = require('react'); - const SvgIcon = require('@material-ui/core/SvgIcon').default; - module.exports = { - __esModule: true, - default: props => React.createElement(SvgIcon, props, { - $$typeof: Symbol.for('react.element'), - type: 'svg', - ref: ref, - key: null, - props: Object.assign({}, props, { - children: ${assetFilename} - }) - }) - };`, - }; - } - - return { code: `module.exports = ${assetFilename};` }; - }, -}; +try { + module.exports = require('@backstage/cli-module-test-jest/config/jestFileTransform'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-test-jest is required to use the jest file transform. ' + + 'Please install it as a dependency.', + ); + } + throw e; +} diff --git a/packages/cli/config/jestRejectNetworkRequests.js b/packages/cli/config/jestRejectNetworkRequests.js index f6f189a60c..c975257b8c 100644 --- a/packages/cli/config/jestRejectNetworkRequests.js +++ b/packages/cli/config/jestRejectNetworkRequests.js @@ -14,57 +14,14 @@ * limitations under the License. */ -const http = require('node:http'); -const https = require('node:https'); - -const errorMessage = 'Network requests are not allowed in tests'; - -const origHttpAgent = http.globalAgent; -const origHttpsAgent = https.globalAgent; -const origFetch = global.fetch; -const origXMLHttpRequest = global.XMLHttpRequest; - -http.globalAgent = new http.Agent({ - lookup() { - throw new Error(errorMessage); - }, -}); - -https.globalAgent = new https.Agent({ - lookup() { - throw new Error(errorMessage); - }, -}); - -const BLOCKING_FETCH_SYMBOL = Symbol.for( - 'backstage.jestRejectNetworkRequests.blockingFetch', -); - -if (global.fetch) { - const blockingFetch = async (input, init) => { - // If global.fetch still has our marker, block the request - if (global.fetch[BLOCKING_FETCH_SYMBOL]) { - throw new Error(errorMessage); - } - // MSW (or something else) wrapped us - pass through - return origFetch(input, init); - }; - blockingFetch[BLOCKING_FETCH_SYMBOL] = true; - global.fetch = blockingFetch; +try { + module.exports = require('@backstage/cli-module-test-jest/config/jestRejectNetworkRequests'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-test-jest is required to use the jest network request rejection. ' + + 'Please install it as a dependency.', + ); + } + throw e; } - -if (global.XMLHttpRequest) { - global.XMLHttpRequest = class { - constructor() { - throw new Error(errorMessage); - } - }; -} - -// Reset overrides after each suite to make sure we don't pollute the test environment -afterAll(() => { - http.globalAgent = origHttpAgent; - https.globalAgent = origHttpsAgent; - global.fetch = origFetch; - global.XMLHttpRequest = origXMLHttpRequest; -}); diff --git a/packages/cli/config/jestSucraseTransform.js b/packages/cli/config/jestSucraseTransform.js index 621b9ee297..fe20351c29 100644 --- a/packages/cli/config/jestSucraseTransform.js +++ b/packages/cli/config/jestSucraseTransform.js @@ -14,74 +14,14 @@ * limitations under the License. */ -const { createHash } = require('node:crypto'); -const { transform } = require('sucrase'); -const sucrasePkg = require('sucrase/package.json'); - -const ESM_REGEX = /\b(?:import|export)\b/; - -function createTransformer(config) { - const process = (source, filePath) => { - let transforms; - - if (filePath.endsWith('.esm.js')) { - transforms = ['imports']; - } else if (filePath.endsWith('.js')) { - // This is a very rough filter to avoid transforming things that we quickly - // can be sure are definitely not ESM modules. - if (ESM_REGEX.test(source)) { - transforms = ['imports', 'jsx']; // JSX within .js is currently allowed - } - } else if (filePath.endsWith('.jsx')) { - transforms = ['jsx', 'imports']; - } else if (filePath.endsWith('.ts')) { - transforms = ['typescript', 'imports']; - } else if (filePath.endsWith('.tsx')) { - transforms = ['typescript', 'jsx', 'imports']; - } - - // Only apply the jest transform to the test files themselves - if (transforms && filePath.includes('.test.')) { - transforms.push('jest'); - } - - if (transforms) { - const { code, sourceMap: map } = transform(source, { - transforms, - filePath, - disableESTransforms: true, - sourceMapOptions: { - compiledFilename: filePath, - }, - }); - if (config.enableSourceMaps) { - const b64 = Buffer.from(JSON.stringify(map), 'utf8').toString('base64'); - const suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${b64}`; - // Include both inline and object source maps, as inline source maps are - // needed for support of some editor integrations. - return { code: `${code}\n${suffix}`, map }; - } - // We only return the `map` result if source maps are enabled, as they - // have a negative impact on the coverage accuracy. - return { code }; - } - - return { code: source }; - }; - - const getCacheKey = sourceText => { - return createHash('sha256') - .update(sourceText) - .update(Buffer.alloc(1)) - .update(sucrasePkg.version) - .update(Buffer.alloc(1)) - .update(JSON.stringify(config)) - .update(Buffer.alloc(1)) - .update('1') // increment whenever the transform logic in this file changes - .digest('hex'); - }; - - return { process, getCacheKey }; +try { + module.exports = require('@backstage/cli-module-test-jest/config/jestSucraseTransform'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-test-jest is required to use the jest Sucrase transform. ' + + 'Please install it as a dependency.', + ); + } + throw e; } - -module.exports = { createTransformer }; diff --git a/packages/cli/config/jestSwcTransform.js b/packages/cli/config/jestSwcTransform.js index 4183349554..4aa6776c22 100644 --- a/packages/cli/config/jestSwcTransform.js +++ b/packages/cli/config/jestSwcTransform.js @@ -13,32 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const { createTransformer: createSwcTransformer } = require('@swc/jest'); -const ESM_REGEX = /\b(?:import|export)\b/; - -function createTransformer(config) { - const swcTransformer = createSwcTransformer({ - inputSourceMap: false, - ...config, - }); - const process = (source, filePath, jestOptions) => { - // Skip transformation of .js files without ESM syntax, we never transform from CJS to ESM - if (filePath.endsWith('.js') && !ESM_REGEX.test(source)) { - return { code: source }; - } - - // Skip transformation of .mjs files, they should only be used if ESM support is available - if (jestOptions.supportsStaticESM && filePath.endsWith('.mjs')) { - return { code: source }; - } - - return swcTransformer.process(source, filePath, jestOptions); - }; - - const getCacheKey = swcTransformer.getCacheKey; - - return { process, getCacheKey }; +try { + module.exports = require('@backstage/cli-module-test-jest/config/jestSwcTransform'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-test-jest is required to use the jest SWC transform. ' + + 'Please install it as a dependency.', + ); + } + throw e; } - -module.exports = { createTransformer }; diff --git a/packages/cli/config/jestYamlTransform.js b/packages/cli/config/jestYamlTransform.js index 7a05274add..85b889498f 100644 --- a/packages/cli/config/jestYamlTransform.js +++ b/packages/cli/config/jestYamlTransform.js @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2020 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. @@ -14,27 +14,14 @@ * limitations under the License. */ -const yaml = require('yaml'); -const crypto = require('node:crypto'); - -function createTransformer(config) { - const process = source => { - const json = JSON.stringify(yaml.parse(source), null, 2); - return { code: `module.exports = ${json}`, map: null }; - }; - - const getCacheKey = sourceText => { - return crypto - .createHash('sha256') - .update(sourceText) - .update(Buffer.alloc(1)) - .update(JSON.stringify(config)) - .update(Buffer.alloc(1)) - .update('1') // increment whenever the transform logic in this file changes - .digest('hex'); - }; - - return { process, getCacheKey }; +try { + module.exports = require('@backstage/cli-module-test-jest/config/jestYamlTransform'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-test-jest is required to use the jest YAML transform. ' + + 'Please install it as a dependency.', + ); + } + throw e; } - -module.exports = { createTransformer }; diff --git a/packages/cli/config/nodeTransform.cjs b/packages/cli/config/nodeTransform.cjs index 15bcdba9bc..83815ebea9 100644 --- a/packages/cli/config/nodeTransform.cjs +++ b/packages/cli/config/nodeTransform.cjs @@ -14,74 +14,14 @@ * limitations under the License. */ -const { pathToFileURL } = require('node:url'); -const { transformSync } = require('@swc/core'); -const { addHook } = require('pirates'); -const { Module } = require('node:module'); - -// This hooks into module resolution and overrides imports of packages that -// exist in the linked workspace to instead be resolved from the linked workspace. -if (process.env.BACKSTAGE_CLI_LINKED_WORKSPACE) { - const { join: joinPath } = require('node:path'); - const { getPackagesSync } = require('@manypkg/get-packages'); - const { packages: linkedPackages, root: linkedRoot } = getPackagesSync( - process.env.BACKSTAGE_CLI_LINKED_WORKSPACE, - ); - - // Matches all packages in the linked workspaces, as well as sub-path exports from them - const replacementRegex = new RegExp( - `^(?:${linkedPackages - .map(pkg => pkg.packageJson.name) - .join('|')})(?:/.*)?$`, - ); - - const origLoad = Module._load; - Module._load = function requireHook(request, parent) { - if (!replacementRegex.test(request)) { - return origLoad.call(this, request, parent); - } - - // The package import that we're overriding will always existing in the root - // node_modules of the linked workspace, so it's enough to override the - // parent paths with that single entry - return origLoad.call(this, request, { - ...parent, - paths: [joinPath(linkedRoot.dir, 'node_modules')], - }); - }; +try { + require('@backstage/cli-module-build/config/nodeTransform.cjs'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-build is required to use the node transform. ' + + 'Please install it as a dependency.', + ); + } + throw e; } - -addHook( - (code, filename) => { - const transformed = transformSync(code, { - filename, - sourceMaps: 'inline', - module: { - type: 'commonjs', - ignoreDynamic: true, - }, - jsc: { - target: 'es2023', - parser: { - syntax: 'typescript', - }, - }, - }); - process.send?.({ type: 'watch', path: filename }); - return transformed.code; - }, - { extensions: ['.ts', '.cts'], ignoreNodeModules: true }, -); - -addHook( - (code, filename) => { - process.send?.({ type: 'watch', path: filename }); - return code; - }, - { extensions: ['.js', '.cjs'], ignoreNodeModules: true }, -); - -// Register module hooks, used by "type": "module" in package.json, .mjs and -// .mts files, as well as dynamic import(...)s, although dynamic imports will be -// handled be the CommonJS hooks in this file if what it points to is CommonJS. -Module.register('./nodeTransformHooks.mjs', pathToFileURL(__filename)); diff --git a/packages/cli/config/nodeTransformHooks.mjs b/packages/cli/config/nodeTransformHooks.mjs index 592867e57a..9fe9b327b5 100644 --- a/packages/cli/config/nodeTransformHooks.mjs +++ b/packages/cli/config/nodeTransformHooks.mjs @@ -14,281 +14,7 @@ * limitations under the License. */ -import { dirname, extname, resolve as resolvePath } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { transformFile } from '@swc/core'; -import { isBuiltin } from 'node:module'; -import { readFile } from 'node:fs/promises'; -import { existsSync } from 'node:fs'; - -// @ts-check - -// No explicit file extension, no type in package.json -const DEFAULT_MODULE_FORMAT = 'commonjs'; - -// Source file extensions to look for when using bundle resolution strategy -const SRC_EXTS = ['.ts', '.js']; -const TS_EXTS = ['.ts', '.mts', '.cts']; -const moduleTypeTable = { - '.mjs': 'module', - '.mts': 'module', - '.cjs': 'commonjs', - '.cts': 'commonjs', - '.ts': undefined, - '.js': undefined, -}; - -/** @type {import('module').ResolveHook} */ -export async function resolve(specifier, context, nextResolve) { - // Built-in modules are handled by the default resolver - if (isBuiltin(specifier)) { - return nextResolve(specifier, context); - } - - const ext = extname(specifier); - - // Unless there's an explicit import attribute, JSON files are loaded with our custom loader that's defined below. - if (ext === '.json' && !context.importAttributes?.type) { - const jsonResult = await nextResolve(specifier, context); - return { - ...jsonResult, - format: 'commonjs', - importAttributes: { type: 'json' }, - }; - } - - // Anything else with an explicit extension is handled by the default - // resolver, except that we help determine the module type where needed. - if (ext !== '') { - return withDetectedModuleType(await nextResolve(specifier, context)); - } - - // Other external modules are handled by the default resolver, but again we - // help determine the module type where needed. - if (!specifier.startsWith('.')) { - return withDetectedModuleType(await nextResolve(specifier, context)); - } - - // The rest of this function handles the case of resolving imports that do not - // specify any extension and might point to a directory with an `index.*` - // file. We resolve those using the same logic as most JS bundlers would, with - // the addition of checking if there's an explicit module format listed in the - // closest `package.json` file. - // - // We use a bundle resolution strategy in order to keep code consistent across - // Backstage codebases that contains code both for Web and Node.js, and to - // support packages with common code that can be used in both environments. - try { - // This is expected to throw, but in the event that this module specifier is - // supported we prefer to use the default resolver. - return await nextResolve(specifier, context); - } catch (error) { - if (error.code === 'ERR_UNSUPPORTED_DIR_IMPORT') { - const spec = `${specifier}${specifier.endsWith('/') ? '' : '/'}index`; - const resolved = await resolveWithoutExt(spec, context, nextResolve); - if (resolved) { - return withDetectedModuleType(resolved); - } - } else if (error.code === 'ERR_MODULE_NOT_FOUND') { - const resolved = await resolveWithoutExt(specifier, context, nextResolve); - if (resolved) { - return withDetectedModuleType(resolved); - } - } - - // Unexpected error or no resolution found - throw error; - } -} - -/** - * Populates the `format` field in the resolved object based on the closest `package.json` file. - * - * @param {import('module').ResolveFnOutput} resolved - * @returns {Promise} - */ -async function withDetectedModuleType(resolved) { - // Already has an explicit format - if (resolved.format) { - return resolved; - } - // Happens in Node.js v22 when there's a package.json without an explicit "type" field. Use the default. - if (resolved.format === null) { - return { ...resolved, format: DEFAULT_MODULE_FORMAT }; - } - - const ext = extname(resolved.url); - - const explicitFormat = moduleTypeTable[ext]; - if (explicitFormat) { - return { - ...resolved, - format: explicitFormat, - }; - } - - // Under normal circumstances .js files should reliably have a format and so - // we should only reach this point for .ts files. However, if additional - // custom loaders are being used the format may not be detected for .js files - // either. As such we don't restrict the file format at this point. - - // TODO(Rugvip): Does this need caching? kept it simple for now but worth exploring - const packageJsonPath = await findPackageJSON(fileURLToPath(resolved.url)); - if (!packageJsonPath) { - return resolved; - } - - const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8')); - return { - ...resolved, - format: packageJson.type ?? DEFAULT_MODULE_FORMAT, - }; -} - -/** - * Find the closest package.json file from the given path. - * - * TODO(Rugvip): This can be replaced with the Node.js built-in with the same name once it is stable. - * @param {string} startPath - * @returns {Promise} - */ -async function findPackageJSON(startPath) { - let path = startPath; - - // Some confidence check to avoid infinite loop - for (let i = 0; i < 1000; i++) { - const packagePath = resolvePath(path, 'package.json'); - if (existsSync(packagePath)) { - return packagePath; - } - - const newPath = dirname(path); - if (newPath === path) { - return undefined; - } - path = newPath; - } - - throw new Error( - `Iteration limit reached when searching for package.json at ${startPath}`, - ); -} - -/** @type {import('module').ResolveHook} */ -async function resolveWithoutExt(specifier, context, nextResolve) { - for (const tryExt of SRC_EXTS) { - try { - const resolved = await nextResolve(specifier + tryExt, { - ...context, - format: 'commonjs', - }); - return { - ...resolved, - format: moduleTypeTable[tryExt] ?? resolved.format, - }; - } catch { - /* ignore */ - } - } - return undefined; -} - -/** @type {import('module').LoadHook} */ -export async function load(url, context, nextLoad) { - // Non-file URLs are handled by the default loader - if (!url.startsWith('file://')) { - return nextLoad(url, context); - } - - // JSON files loaded as CommonJS are handled by this custom loader, because - // the default one doesn't work. For JSON loading to work we'd need the - // synchronous hooks that aren't supported yet, or avoid using the CommonJS - // compatibility. - if ( - context.format === 'commonjs' && - context.importAttributes?.type === 'json' - ) { - try { - // TODO(Rugvip): Make sure this is valid JSON - const content = await readFile(fileURLToPath(url), 'utf8'); - return { - source: `module.exports = (${content})`, - format: 'commonjs', - shortCircuit: true, - }; - } catch { - // Let the default loader generate the error - return nextLoad(url, context); - } - } - - const ext = extname(url); - - // Non-TS files are handled by the default loader - if (!TS_EXTS.includes(ext)) { - return nextLoad(url, context); - } - - const format = context.format ?? DEFAULT_MODULE_FORMAT; - - // We have two choices at this point, we can either transform CommonJS files - // and return the transformed source code, or let the default loader handle - // them. If we transform them ourselves we will enter CommonJS compatibility - // mode in the new module system in Node.js, this effectively means all - // CommonJS loaded via `require` calls from this point will all be treated as - // if it was loaded via `import` calls from modules. - // - // The CommonJS compatibility layer will try to identify named exports and - // make them available directly, which is convenient as it avoids things like - // `import(...).then(m => m.default.foo)`, allowing you to instead write - // `import(...).then(m => m.foo)`. The compatibility layer doesn't always work - // all that well though, and can lead to module loading issues in many cases, - // especially for older code. - - // This `if` block opts-out of using CommonJS compatibility mode by default, - // and instead leaves it to our existing loader to transform CommonJS. We do - // however use compatibility mode for the more explicit .cts file extension, - // allows for a way to opt-in to the new behavior. - // - // TODO(Rugvip): Once the synchronous hooks API is available for us to use, we might be able to adopt that instead - if (format === 'commonjs' && ext !== '.cts') { - return nextLoad(url, { ...context, format }); - } - - // If the Node.js version we're running supports TypeScript, i.e. type - // stripping, we hand over to the default loader. This is done for all cases - // except if we're loading a .ts file that's been resolved to CommonJS format. - // This is because these files aren't actually CommonJS in the Backstage build - // system, and need to be transformed to CommonJS. - if ( - format === 'module-typescript' || - (format === 'module-commonjs' && ext !== '.ts') - ) { - return nextLoad(url, { ...context, format }); - } - - const transformed = await transformFile(fileURLToPath(url), { - sourceMaps: 'inline', - module: { - type: format === 'module' ? 'es6' : 'commonjs', - ignoreDynamic: true, - - // This helps the Node.js CommonJS compat layer identify named exports. - exportInteropAnnotation: true, - }, - jsc: { - target: 'es2023', - parser: { - syntax: 'typescript', - }, - }, - }); - - return { - ...context, - shortCircuit: true, - source: transformed.code, - format, - responseURL: url, - }; -} +export { + resolve, + load, +} from '@backstage/cli-module-build/config/nodeTransformHooks.mjs'; diff --git a/packages/cli/config/webpack-public-path.js b/packages/cli/config/webpack-public-path.js index 3e14e96eb9..d1c36222c9 100644 --- a/packages/cli/config/webpack-public-path.js +++ b/packages/cli/config/webpack-public-path.js @@ -14,18 +14,14 @@ * limitations under the License. */ -// This script is used to pick up and set the public path of the Webpack bundle -// at runtime. The meta tag is injected by the app build, but only present in -// the `index.html.tmpl` file. The runtime value of the meta tag is populated by -// the app backend, when it templates the final `index.html` file. -// -// This is needed for additional chunks to use the correct public path, and it -// is not possible to set the `__webpack_public_path__` variable outside of the -// build itself. The Webpack output also does not read any tags or -// similar, this seems to be the only way to dynamically configure the public -// path at runtime. -const el = document.querySelector('meta[name="backstage-public-path"]'); -const path = el?.getAttribute('content'); -if (path) { - __webpack_public_path__ = path; +try { + require('@backstage/cli-module-build/config/webpack-public-path'); +} catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + '@backstage/cli-module-build is required to use the webpack public path configuration. ' + + 'Please install it as a dependency.', + ); + } + throw e; } diff --git a/packages/cli/package.json b/packages/cli/package.json index 600f150654..4ba287a9ef 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -49,6 +49,8 @@ "dependencies": { "@backstage/cli-common": "workspace:^", "@backstage/cli-defaults": "workspace:^", + "@backstage/cli-module-build": "workspace:^", + "@backstage/cli-module-test-jest": "workspace:^", "@backstage/cli-node": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/eslint-plugin": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 643fa1d573..d87b8e32d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2869,6 +2869,7 @@ __metadata: "@rspack/core": "npm:^1.4.11" "@rspack/dev-server": "npm:^1.1.4" "@rspack/plugin-react-refresh": "npm:^1.4.3" + "@swc/core": "npm:^1.15.6" "@types/fs-extra": "npm:^11.0.0" "@types/lodash": "npm:^4.14.151" "@types/npm-packlist": "npm:^3.0.0" @@ -2893,6 +2894,7 @@ __metadata: node-stdlib-browser: "npm:^1.3.1" npm-packlist: "npm:^5.0.0" p-queue: "npm:^6.6.2" + pirates: "npm:^4.0.6" postcss: "npm:^8.1.0" postcss-import: "npm:^16.1.0" process: "npm:^0.11.10" @@ -3084,10 +3086,27 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" + "@swc/core": "npm:^1.15.6" + "@swc/jest": "npm:^0.2.39" cleye: "npm:^2.3.0" + cross-fetch: "npm:^4.0.0" + fs-extra: "npm:^11.2.0" + glob: "npm:^7.1.7" + jest-css-modules: "npm:^2.1.0" + sucrase: "npm:^3.20.2" yargs: "npm:^16.2.0" peerDependencies: + "@jest/environment-jsdom-abstract": ^30.0.0 jest-cli: ^29.0.0 || ^30.0.0 + jest-environment-jsdom: "*" + jsdom: ^27.1.0 + peerDependenciesMeta: + "@jest/environment-jsdom-abstract": + optional: true + jest-environment-jsdom: + optional: true + jsdom: + optional: true bin: cli-module-test-jest: bin/cli-module-test-jest languageName: unknown @@ -3141,6 +3160,8 @@ __metadata: "@backstage/catalog-client": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/cli-defaults": "workspace:^" + "@backstage/cli-module-build": "workspace:^" + "@backstage/cli-module-test-jest": "workspace:^" "@backstage/cli-node": "workspace:^" "@backstage/config": "workspace:^" "@backstage/core-app-api": "workspace:^" From 6395e35c6a429e22157d981bd97019e856113255 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 23:12:59 +0100 Subject: [PATCH 38/45] Generate CLI reports for cli-module packages Include cli-module role in CLI report generation alongside the existing cli role. Packages without a bin field are silently skipped. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-auth/cli-report.md | 96 ++++++++++ packages/cli-module-build/cli-report.md | 156 ++++++++++++++++ packages/cli-module-config/cli-report.md | 109 +++++++++++ .../cli-report.md | 26 +++ packages/cli-module-info/cli-report.md | 28 +++ packages/cli-module-lint/cli-report.md | 73 ++++++++ packages/cli-module-maintenance/cli-report.md | 52 ++++++ packages/cli-module-migrate/cli-report.md | 105 +++++++++++ packages/cli-module-new/cli-report.md | 34 ++++ packages/cli-module-test-jest/cli-report.md | 170 ++++++++++++++++++ .../cli-module-translations/cli-report.md | 53 ++++++ .../api-reports/categorizePackageDirs.ts | 5 +- .../cli-reports/runCliExtraction.ts | 2 +- 13 files changed, 906 insertions(+), 3 deletions(-) create mode 100644 packages/cli-module-auth/cli-report.md create mode 100644 packages/cli-module-build/cli-report.md create mode 100644 packages/cli-module-config/cli-report.md create mode 100644 packages/cli-module-create-github-app/cli-report.md create mode 100644 packages/cli-module-info/cli-report.md create mode 100644 packages/cli-module-lint/cli-report.md create mode 100644 packages/cli-module-maintenance/cli-report.md create mode 100644 packages/cli-module-migrate/cli-report.md create mode 100644 packages/cli-module-new/cli-report.md create mode 100644 packages/cli-module-test-jest/cli-report.md create mode 100644 packages/cli-module-translations/cli-report.md diff --git a/packages/cli-module-auth/cli-report.md b/packages/cli-module-auth/cli-report.md new file mode 100644 index 0000000000..1b382040a2 --- /dev/null +++ b/packages/cli-module-auth/cli-report.md @@ -0,0 +1,96 @@ +## CLI Report file for "@backstage/cli-module-auth" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-auth` + +``` +Usage: @backstage/cli-module-auth [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + auth [command] + help [command] +``` + +### `cli-module-auth auth` + +``` +Usage: @backstage/cli-module-auth auth [options] [command] [command] + +Options: + -h, --help + +Commands: + help [command] + list + login + logout + print-token + select + show +``` + +### `cli-module-auth auth list` + +``` +Usage: @backstage/cli-module-auth auth list + +Options: + -h, --help +``` + +### `cli-module-auth auth login` + +``` +Usage: @backstage/cli-module-auth auth login + +Options: + --backend-url + --instance + --no-browser + -h, --help +``` + +### `cli-module-auth auth logout` + +``` +Usage: @backstage/cli-module-auth auth logout + +Options: + --instance + -h, --help +``` + +### `cli-module-auth auth print-token` + +``` +Usage: @backstage/cli-module-auth auth print-token + +Options: + --instance + -h, --help +``` + +### `cli-module-auth auth select` + +``` +Usage: @backstage/cli-module-auth auth select + +Options: + --instance + -h, --help +``` + +### `cli-module-auth auth show` + +``` +Usage: @backstage/cli-module-auth auth show + +Options: + --instance + -h, --help +``` diff --git a/packages/cli-module-build/cli-report.md b/packages/cli-module-build/cli-report.md new file mode 100644 index 0000000000..b2240e0523 --- /dev/null +++ b/packages/cli-module-build/cli-report.md @@ -0,0 +1,156 @@ +## CLI Report file for "@backstage/cli-module-build" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-build` + +``` +Usage: @backstage/cli-module-build [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + build-workspace + help [command] + package [command] + repo [command] +``` + +### `cli-module-build build-workspace` + +``` +Usage: @backstage/cli-module-build build-workspace [packages...] + +Options: + --always-pack + -h, --help +``` + +### `cli-module-build package` + +``` +Usage: @backstage/cli-module-build package [options] [command] [command] + +Options: + -h, --help + +Commands: + build + clean + help [command] + postpack + prepack + start +``` + +### `cli-module-build package build` + +``` +Usage: @backstage/cli-module-build package build + +Options: + --config + --minify + --module-federation + --role + --skip-build-dependencies + --stats + -h, --help +``` + +### `cli-module-build package clean` + +``` +Usage: @backstage/cli-module-build package clean + +Options: + -h, --help +``` + +### `cli-module-build package postpack` + +``` +Usage: @backstage/cli-module-build package postpack + +Options: + -h, --help +``` + +### `cli-module-build package prepack` + +``` +Usage: @backstage/cli-module-build package prepack + +Options: + -h, --help +``` + +### `cli-module-build package start` + +``` +Usage: @backstage/cli-module-build package start + +Options: + --check + --config + --entrypoint + --inspect + --inspect-brk + --link + --require + --role + -h, --help +``` + +### `cli-module-build repo` + +``` +Usage: @backstage/cli-module-build repo [options] [command] [command] + +Options: + -h, --help + +Commands: + build + clean + help [command] + start +``` + +### `cli-module-build repo build` + +``` +Usage: @backstage/cli-module-build repo build + +Options: + --all + --minify + --since + -h, --help +``` + +### `cli-module-build repo clean` + +``` +Usage: @backstage/cli-module-build repo clean + +Options: + -h, --help +``` + +### `cli-module-build repo start` + +``` +Usage: @backstage/cli-module-build repo start [packages...] + +Options: + --config + --inspect + --inspect-brk + --link + --plugin + --require + -h, --help +``` diff --git a/packages/cli-module-config/cli-report.md b/packages/cli-module-config/cli-report.md new file mode 100644 index 0000000000..6cb8a15d62 --- /dev/null +++ b/packages/cli-module-config/cli-report.md @@ -0,0 +1,109 @@ +## CLI Report file for "@backstage/cli-module-config" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-config` + +``` +Usage: @backstage/cli-module-config [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + config [command] + config:check + config:docs + config:print + config:schema + help [command] +``` + +### `cli-module-config config` + +``` +Usage: @backstage/cli-module-config config [options] [command] [command] + +Options: + -h, --help + +Commands: + docs + help [command] + schema +``` + +### `cli-module-config config docs` + +``` +Usage: @backstage/cli-module-config config docs + +Options: + --package + -h, --help +``` + +### `cli-module-config config schema` + +``` +Usage: @backstage/cli-module-config config schema + +Options: + --format + --merge + --package + -h, --help +``` + +### `cli-module-config config:check` + +``` +Usage: @backstage/cli-module-config config:check + +Options: + --config + --deprecated + --frontend + --lax + --package + --strict + -h, --help +``` + +### `cli-module-config config:docs` + +``` +Usage: @backstage/cli-module-config config:docs + +Options: + --package + -h, --help +``` + +### `cli-module-config config:print` + +``` +Usage: @backstage/cli-module-config config:print + +Options: + --config + --format + --frontend + --lax + --package + --with-secrets + -h, --help +``` + +### `cli-module-config config:schema` + +``` +Usage: @backstage/cli-module-config config:schema + +Options: + --format + --merge + --package + -h, --help +``` diff --git a/packages/cli-module-create-github-app/cli-report.md b/packages/cli-module-create-github-app/cli-report.md new file mode 100644 index 0000000000..a12ea68bf2 --- /dev/null +++ b/packages/cli-module-create-github-app/cli-report.md @@ -0,0 +1,26 @@ +## CLI Report file for "@backstage/cli-module-create-github-app" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-create-github-app` + +``` +Usage: @backstage/cli-module-create-github-app [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + create-github-app + help [command] +``` + +### `cli-module-create-github-app create-github-app` + +``` +Usage: @backstage/cli-module-create-github-app create-github-app + +Options: + -h, --help +``` diff --git a/packages/cli-module-info/cli-report.md b/packages/cli-module-info/cli-report.md new file mode 100644 index 0000000000..f292e46a18 --- /dev/null +++ b/packages/cli-module-info/cli-report.md @@ -0,0 +1,28 @@ +## CLI Report file for "@backstage/cli-module-info" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-info` + +``` +Usage: @backstage/cli-module-info [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + help [command] + info +``` + +### `cli-module-info info` + +``` +Usage: @backstage/cli-module-info info + +Options: + --format + --include + -h, --help +``` diff --git a/packages/cli-module-lint/cli-report.md b/packages/cli-module-lint/cli-report.md new file mode 100644 index 0000000000..c577759e0c --- /dev/null +++ b/packages/cli-module-lint/cli-report.md @@ -0,0 +1,73 @@ +## CLI Report file for "@backstage/cli-module-lint" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-lint` + +``` +Usage: @backstage/cli-module-lint [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + help [command] + package [command] + repo [command] +``` + +### `cli-module-lint package` + +``` +Usage: @backstage/cli-module-lint package [options] [command] [command] + +Options: + -h, --help + +Commands: + help [command] + lint +``` + +### `cli-module-lint package lint` + +``` +Usage: @backstage/cli-module-lint package lint [directories...] + +Options: + --fix + --format + --max-warnings + --output-file + -h, --help +``` + +### `cli-module-lint repo` + +``` +Usage: @backstage/cli-module-lint repo [options] [command] [command] + +Options: + -h, --help + +Commands: + help [command] + lint +``` + +### `cli-module-lint repo lint` + +``` +Usage: @backstage/cli-module-lint repo lint + +Options: + --fix + --format + --max-warnings + --output-file + --since + --success-cache + --success-cache-dir + -h, --help +``` diff --git a/packages/cli-module-maintenance/cli-report.md b/packages/cli-module-maintenance/cli-report.md new file mode 100644 index 0000000000..66b9950328 --- /dev/null +++ b/packages/cli-module-maintenance/cli-report.md @@ -0,0 +1,52 @@ +## CLI Report file for "@backstage/cli-module-maintenance" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-maintenance` + +``` +Usage: @backstage/cli-module-maintenance [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + help [command] + repo [command] +``` + +### `cli-module-maintenance repo` + +``` +Usage: @backstage/cli-module-maintenance repo [options] [command] [command] + +Options: + -h, --help + +Commands: + fix + help [command] + list-deprecations +``` + +### `cli-module-maintenance repo fix` + +``` +Usage: @backstage/cli-module-maintenance repo fix + +Options: + --check + --publish + -h, --help +``` + +### `cli-module-maintenance repo list-deprecations` + +``` +Usage: @backstage/cli-module-maintenance repo list-deprecations + +Options: + --json + -h, --help +``` diff --git a/packages/cli-module-migrate/cli-report.md b/packages/cli-module-migrate/cli-report.md new file mode 100644 index 0000000000..06a60cdfaf --- /dev/null +++ b/packages/cli-module-migrate/cli-report.md @@ -0,0 +1,105 @@ +## CLI Report file for "@backstage/cli-module-migrate" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-migrate` + +``` +Usage: @backstage/cli-module-migrate [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + help [command] + migrate [command] + versions:bump + versions:migrate +``` + +### `cli-module-migrate migrate` + +``` +Usage: @backstage/cli-module-migrate migrate [options] [command] [command] + +Options: + -h, --help + +Commands: + help [command] + package-exports + package-lint-configs + package-roles + package-scripts + react-router-deps +``` + +### `cli-module-migrate migrate package-exports` + +``` +Usage: @backstage/cli-module-migrate migrate package-exports + +Options: + -h, --help +``` + +### `cli-module-migrate migrate package-lint-configs` + +``` +Usage: @backstage/cli-module-migrate migrate package-lint-configs + +Options: + -h, --help +``` + +### `cli-module-migrate migrate package-roles` + +``` +Usage: @backstage/cli-module-migrate migrate package-roles + +Options: + -h, --help +``` + +### `cli-module-migrate migrate package-scripts` + +``` +Usage: @backstage/cli-module-migrate migrate package-scripts + +Options: + -h, --help +``` + +### `cli-module-migrate migrate react-router-deps` + +``` +Usage: @backstage/cli-module-migrate migrate react-router-deps + +Options: + -h, --help +``` + +### `cli-module-migrate versions:bump` + +``` +Usage: @backstage/cli-module-migrate versions:bump + +Options: + --pattern + --release + --skip-install + --skip-migrate + -h, --help +``` + +### `cli-module-migrate versions:migrate` + +``` +Usage: @backstage/cli-module-migrate versions:migrate + +Options: + --pattern + --skip-code-changes + -h, --help +``` diff --git a/packages/cli-module-new/cli-report.md b/packages/cli-module-new/cli-report.md new file mode 100644 index 0000000000..2c414fc747 --- /dev/null +++ b/packages/cli-module-new/cli-report.md @@ -0,0 +1,34 @@ +## CLI Report file for "@backstage/cli-module-new" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-new` + +``` +Usage: @backstage/cli-module-new [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + help [command] + new +``` + +### `cli-module-new new` + +``` +Usage: @backstage/cli-module-new new + +Options: + --base-version + --license + --npm-registry + --option + --private + --scope + --select + --skip-install + -h, --help +``` diff --git a/packages/cli-module-test-jest/cli-report.md b/packages/cli-module-test-jest/cli-report.md new file mode 100644 index 0000000000..ca1d390ed7 --- /dev/null +++ b/packages/cli-module-test-jest/cli-report.md @@ -0,0 +1,170 @@ +## CLI Report file for "@backstage/cli-module-test-jest" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-test-jest` + +``` +Usage: @backstage/cli-module-test-jest [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + help [command] + package [command] + repo [command] +``` + +### `cli-module-test-jest package` + +``` +Usage: @backstage/cli-module-test-jest package [options] [command] [command] + +Options: + -h, --help + +Commands: + help [command] + test +``` + +### `cli-module-test-jest package test` + +``` +Usage: cli-module-test-jest [--config=] [TestPathPatterns] + +Options: + --all + --automock + --cache + --cacheDirectory + --changedFilesWithAncestor + --changedSince + --ci + --clearCache + --clearMocks + --collectCoverage + --collectCoverageFrom + --color + --colors + --coverage + --coverageDirectory + --coveragePathIgnorePatterns + --coverageProvider + --coverageReporters + --coverageThreshold + --debug + --detectLeaks + --detectOpenHandles + --errorOnDeprecated + --filter + --findRelatedTests + --forceExit + --globalSetup + --globalTeardown + --globals + --haste + --ignoreProjects + --injectGlobals + --json + --lastCommit + --listTests + --logHeapUsage + --maxConcurrency + --moduleDirectories + --moduleFileExtensions + --moduleNameMapper + --modulePathIgnorePatterns + --modulePaths + --noStackTrace + --notify + --notifyMode + --openHandlesTimeout + --outputFile + --passWithNoTests + --preset + --prettierPath + --projects + --randomize + --reporters + --resetMocks + --resetModules + --resolver + --restoreMocks + --rootDir + --roots + --runTestsByPath + --runner + --seed + --selectProjects + --setupFiles + --setupFilesAfterEnv + --shard + --showConfig + --showSeed + --silent + --skipFilter + --snapshotSerializers + --testEnvironment, --env + --testEnvironmentOptions + --testFailureExitCode + --testLocationInResults + --testMatch + --testPathIgnorePatterns + --testPathPatterns + --testRegex + --testResultsProcessor + --testRunner + --testSequencer + --testTimeout + --transform + --transformIgnorePatterns + --unmockedModulePathPatterns + --useStderr + --verbose + --version + --waitForUnhandledRejections + --watch + --watchAll + --watchPathIgnorePatterns + --watchman + --workerThreads + -b, --bail + -c, --config + -e, --expand + -f, --onlyFailures + -h, --help + -i, --runInBand + -o, --onlyChanged + -t, --testNamePattern + -u, --updateSnapshot + -w, --maxWorkers +``` + +### `cli-module-test-jest repo` + +``` +Usage: @backstage/cli-module-test-jest repo [options] [command] [command] + +Options: + -h, --help + +Commands: + help [command] + test +``` + +### `cli-module-test-jest repo test` + +``` +Usage: @backstage/cli-module-test-jest repo test + +Options: + --jest-help + --since + --success-cache + --success-cache-dir + -h, --help +``` diff --git a/packages/cli-module-translations/cli-report.md b/packages/cli-module-translations/cli-report.md new file mode 100644 index 0000000000..9b2d5ef3b4 --- /dev/null +++ b/packages/cli-module-translations/cli-report.md @@ -0,0 +1,53 @@ +## CLI Report file for "@backstage/cli-module-translations" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `cli-module-translations` + +``` +Usage: @backstage/cli-module-translations [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + help [command] + translations [command] +``` + +### `cli-module-translations translations` + +``` +Usage: @backstage/cli-module-translations translations [options] [command] [command] + +Options: + -h, --help + +Commands: + export + help [command] + import +``` + +### `cli-module-translations translations export` + +``` +Usage: @backstage/cli-module-translations translations export + +Options: + --output + --pattern + -h, --help +``` + +### `cli-module-translations translations import` + +``` +Usage: @backstage/cli-module-translations translations import + +Options: + --input + --output + -h, --help +``` diff --git a/packages/repo-tools/src/commands/api-reports/categorizePackageDirs.ts b/packages/repo-tools/src/commands/api-reports/categorizePackageDirs.ts index 973c7b8acb..6fdb890100 100644 --- a/packages/repo-tools/src/commands/api-reports/categorizePackageDirs.ts +++ b/packages/repo-tools/src/commands/api-reports/categorizePackageDirs.ts @@ -54,9 +54,10 @@ export async function categorizePackageDirs(packageDirs: string[]) { if (pkgJson?.backstage?.inline) { return; } - if (role === 'cli') { + if (role === 'cli' || role === 'cli-module') { cliPackageDirs.push(dir); - } else if (role !== 'frontend' && role !== 'backend') { + } + if (role !== 'cli' && role !== 'frontend' && role !== 'backend') { tsPackageDirs.push(dir); } } diff --git a/packages/repo-tools/src/commands/api-reports/cli-reports/runCliExtraction.ts b/packages/repo-tools/src/commands/api-reports/cli-reports/runCliExtraction.ts index ae49c95f39..7dfbba51ec 100644 --- a/packages/repo-tools/src/commands/api-reports/cli-reports/runCliExtraction.ts +++ b/packages/repo-tools/src/commands/api-reports/cli-reports/runCliExtraction.ts @@ -132,7 +132,7 @@ export async function runCliExtraction({ const pkgJson = await fs.readJson(resolvePath(fullDir, 'package.json')); if (!pkgJson.bin) { - throw new Error(`CLI Package in ${packageDir} has no bin field`); + continue; } const models = new Array(); From ac96393a12af221ee6fef72fd269fd643ef6fc35 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 23:30:19 +0100 Subject: [PATCH 39/45] Fix jest peer dependency in cli-module-test-jest Change peer dependency from jest-cli to jest to match the actual runtime usage of require('jest') and the original @backstage/cli peer dependency declaration. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-module-test-jest/package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli-module-test-jest/package.json b/packages/cli-module-test-jest/package.json index f83558327c..36dd8fafdf 100644 --- a/packages/cli-module-test-jest/package.json +++ b/packages/cli-module-test-jest/package.json @@ -50,7 +50,7 @@ }, "peerDependencies": { "@jest/environment-jsdom-abstract": "^30.0.0", - "jest-cli": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", "jest-environment-jsdom": "*", "jsdom": "^27.1.0" }, diff --git a/yarn.lock b/yarn.lock index d87b8e32d1..275cf38895 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3097,7 +3097,7 @@ __metadata: yargs: "npm:^16.2.0" peerDependencies: "@jest/environment-jsdom-abstract": ^30.0.0 - jest-cli: ^29.0.0 || ^30.0.0 + jest: ^29.0.0 || ^30.0.0 jest-environment-jsdom: "*" jsdom: ^27.1.0 peerDependenciesMeta: From b76bbfb461a0350f15e15677634ad697c1dd6bde Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 15 Mar 2026 23:54:51 +0100 Subject: [PATCH 40/45] Exclude cli-report files from stale API report detection The runApiExtraction function was detecting cli-report.md files as stale API reports because they matched the report filename pattern. These files are managed by runCliExtraction instead and should be excluded from the stale report check. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../src/commands/api-reports/api-reports/runApiExtraction.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/repo-tools/src/commands/api-reports/api-reports/runApiExtraction.ts b/packages/repo-tools/src/commands/api-reports/api-reports/runApiExtraction.ts index 787a2cb3f4..6091237fae 100644 --- a/packages/repo-tools/src/commands/api-reports/api-reports/runApiExtraction.ts +++ b/packages/repo-tools/src/commands/api-reports/api-reports/runApiExtraction.ts @@ -174,6 +174,7 @@ export async function runApiExtraction({ filename => // https://regex101.com/r/QDZIV0/2 filename !== 'knip-report.md' && + !filename.startsWith('cli-report') && !filename.endsWith('.sql.md') && // this has to temporarily match all old api report formats filename.match(/^.*?(api-)?report(-[^.-]+)?(.*?)\.md$/), From 26eab3bf83d9427ecadecea5d0628c39b61c0590 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 12:27:08 +0100 Subject: [PATCH 41/45] Rename CLI module bin entries to use backstage prefix Rename all bin entries from `cli-module-*` to `backstage-cli-module-*` to establish a clear namespace for Backstage CLI tooling. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- ...-module-auth => backstage-cli-module-auth} | 0 packages/cli-module-auth/cli-report.md | 16 ++++++------- packages/cli-module-auth/package.json | 2 +- ...odule-build => backstage-cli-module-build} | 0 packages/cli-module-build/cli-report.md | 24 +++++++++---------- packages/cli-module-build/package.json | 2 +- ...ule-config => backstage-cli-module-config} | 0 packages/cli-module-config/cli-report.md | 16 ++++++------- packages/cli-module-config/package.json | 2 +- ...=> backstage-cli-module-create-github-app} | 0 .../cli-report.md | 4 ++-- .../cli-module-create-github-app/package.json | 2 +- ...-module-info => backstage-cli-module-info} | 0 packages/cli-module-info/cli-report.md | 4 ++-- packages/cli-module-info/package.json | 2 +- ...-module-lint => backstage-cli-module-lint} | 0 packages/cli-module-lint/cli-report.md | 10 ++++---- packages/cli-module-lint/package.json | 2 +- ...nance => backstage-cli-module-maintenance} | 0 packages/cli-module-maintenance/cli-report.md | 8 +++---- packages/cli-module-maintenance/package.json | 2 +- ...e-migrate => backstage-cli-module-migrate} | 0 packages/cli-module-migrate/cli-report.md | 18 +++++++------- packages/cli-module-migrate/package.json | 2 +- ...li-module-new => backstage-cli-module-new} | 0 packages/cli-module-new/cli-report.md | 4 ++-- packages/cli-module-new/package.json | 2 +- ...st-jest => backstage-cli-module-test-jest} | 0 packages/cli-module-test-jest/cli-report.md | 12 +++++----- packages/cli-module-test-jest/package.json | 2 +- ...ions => backstage-cli-module-translations} | 0 .../cli-module-translations/cli-report.md | 8 +++---- packages/cli-module-translations/package.json | 2 +- yarn.lock | 22 ++++++++--------- 34 files changed, 84 insertions(+), 84 deletions(-) rename packages/cli-module-auth/bin/{cli-module-auth => backstage-cli-module-auth} (100%) rename packages/cli-module-build/bin/{cli-module-build => backstage-cli-module-build} (100%) rename packages/cli-module-config/bin/{cli-module-config => backstage-cli-module-config} (100%) rename packages/cli-module-create-github-app/bin/{cli-module-create-github-app => backstage-cli-module-create-github-app} (100%) rename packages/cli-module-info/bin/{cli-module-info => backstage-cli-module-info} (100%) rename packages/cli-module-lint/bin/{cli-module-lint => backstage-cli-module-lint} (100%) rename packages/cli-module-maintenance/bin/{cli-module-maintenance => backstage-cli-module-maintenance} (100%) rename packages/cli-module-migrate/bin/{cli-module-migrate => backstage-cli-module-migrate} (100%) rename packages/cli-module-new/bin/{cli-module-new => backstage-cli-module-new} (100%) rename packages/cli-module-test-jest/bin/{cli-module-test-jest => backstage-cli-module-test-jest} (100%) rename packages/cli-module-translations/bin/{cli-module-translations => backstage-cli-module-translations} (100%) diff --git a/packages/cli-module-auth/bin/cli-module-auth b/packages/cli-module-auth/bin/backstage-cli-module-auth similarity index 100% rename from packages/cli-module-auth/bin/cli-module-auth rename to packages/cli-module-auth/bin/backstage-cli-module-auth diff --git a/packages/cli-module-auth/cli-report.md b/packages/cli-module-auth/cli-report.md index 1b382040a2..8b4c98766f 100644 --- a/packages/cli-module-auth/cli-report.md +++ b/packages/cli-module-auth/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-auth` +### `backstage-cli-module-auth` ``` Usage: @backstage/cli-module-auth [options] [command] @@ -16,7 +16,7 @@ Commands: help [command] ``` -### `cli-module-auth auth` +### `backstage-cli-module-auth auth` ``` Usage: @backstage/cli-module-auth auth [options] [command] [command] @@ -34,7 +34,7 @@ Commands: show ``` -### `cli-module-auth auth list` +### `backstage-cli-module-auth auth list` ``` Usage: @backstage/cli-module-auth auth list @@ -43,7 +43,7 @@ Options: -h, --help ``` -### `cli-module-auth auth login` +### `backstage-cli-module-auth auth login` ``` Usage: @backstage/cli-module-auth auth login @@ -55,7 +55,7 @@ Options: -h, --help ``` -### `cli-module-auth auth logout` +### `backstage-cli-module-auth auth logout` ``` Usage: @backstage/cli-module-auth auth logout @@ -65,7 +65,7 @@ Options: -h, --help ``` -### `cli-module-auth auth print-token` +### `backstage-cli-module-auth auth print-token` ``` Usage: @backstage/cli-module-auth auth print-token @@ -75,7 +75,7 @@ Options: -h, --help ``` -### `cli-module-auth auth select` +### `backstage-cli-module-auth auth select` ``` Usage: @backstage/cli-module-auth auth select @@ -85,7 +85,7 @@ Options: -h, --help ``` -### `cli-module-auth auth show` +### `backstage-cli-module-auth auth show` ``` Usage: @backstage/cli-module-auth auth show diff --git a/packages/cli-module-auth/package.json b/packages/cli-module-auth/package.json index c3e2d47224..86bb491f7a 100644 --- a/packages/cli-module-auth/package.json +++ b/packages/cli-module-auth/package.json @@ -52,5 +52,5 @@ "optionalDependencies": { "keytar": "^7.9.0" }, - "bin": "bin/cli-module-auth" + "bin": "bin/backstage-cli-module-auth" } diff --git a/packages/cli-module-build/bin/cli-module-build b/packages/cli-module-build/bin/backstage-cli-module-build similarity index 100% rename from packages/cli-module-build/bin/cli-module-build rename to packages/cli-module-build/bin/backstage-cli-module-build diff --git a/packages/cli-module-build/cli-report.md b/packages/cli-module-build/cli-report.md index b2240e0523..1c11022dc8 100644 --- a/packages/cli-module-build/cli-report.md +++ b/packages/cli-module-build/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-build` +### `backstage-cli-module-build` ``` Usage: @backstage/cli-module-build [options] [command] @@ -18,7 +18,7 @@ Commands: repo [command] ``` -### `cli-module-build build-workspace` +### `backstage-cli-module-build build-workspace` ``` Usage: @backstage/cli-module-build build-workspace [packages...] @@ -28,7 +28,7 @@ Options: -h, --help ``` -### `cli-module-build package` +### `backstage-cli-module-build package` ``` Usage: @backstage/cli-module-build package [options] [command] [command] @@ -45,7 +45,7 @@ Commands: start ``` -### `cli-module-build package build` +### `backstage-cli-module-build package build` ``` Usage: @backstage/cli-module-build package build @@ -60,7 +60,7 @@ Options: -h, --help ``` -### `cli-module-build package clean` +### `backstage-cli-module-build package clean` ``` Usage: @backstage/cli-module-build package clean @@ -69,7 +69,7 @@ Options: -h, --help ``` -### `cli-module-build package postpack` +### `backstage-cli-module-build package postpack` ``` Usage: @backstage/cli-module-build package postpack @@ -78,7 +78,7 @@ Options: -h, --help ``` -### `cli-module-build package prepack` +### `backstage-cli-module-build package prepack` ``` Usage: @backstage/cli-module-build package prepack @@ -87,7 +87,7 @@ Options: -h, --help ``` -### `cli-module-build package start` +### `backstage-cli-module-build package start` ``` Usage: @backstage/cli-module-build package start @@ -104,7 +104,7 @@ Options: -h, --help ``` -### `cli-module-build repo` +### `backstage-cli-module-build repo` ``` Usage: @backstage/cli-module-build repo [options] [command] [command] @@ -119,7 +119,7 @@ Commands: start ``` -### `cli-module-build repo build` +### `backstage-cli-module-build repo build` ``` Usage: @backstage/cli-module-build repo build @@ -131,7 +131,7 @@ Options: -h, --help ``` -### `cli-module-build repo clean` +### `backstage-cli-module-build repo clean` ``` Usage: @backstage/cli-module-build repo clean @@ -140,7 +140,7 @@ Options: -h, --help ``` -### `cli-module-build repo start` +### `backstage-cli-module-build repo start` ``` Usage: @backstage/cli-module-build repo start [packages...] diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index 519b24b701..27f4fd3903 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -19,7 +19,7 @@ "license": "Apache-2.0", "main": "src/index.ts", "types": "src/index.ts", - "bin": "bin/cli-module-build", + "bin": "bin/backstage-cli-module-build", "files": [ "dist", "bin", diff --git a/packages/cli-module-config/bin/cli-module-config b/packages/cli-module-config/bin/backstage-cli-module-config similarity index 100% rename from packages/cli-module-config/bin/cli-module-config rename to packages/cli-module-config/bin/backstage-cli-module-config diff --git a/packages/cli-module-config/cli-report.md b/packages/cli-module-config/cli-report.md index 6cb8a15d62..953c347951 100644 --- a/packages/cli-module-config/cli-report.md +++ b/packages/cli-module-config/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-config` +### `backstage-cli-module-config` ``` Usage: @backstage/cli-module-config [options] [command] @@ -20,7 +20,7 @@ Commands: help [command] ``` -### `cli-module-config config` +### `backstage-cli-module-config config` ``` Usage: @backstage/cli-module-config config [options] [command] [command] @@ -34,7 +34,7 @@ Commands: schema ``` -### `cli-module-config config docs` +### `backstage-cli-module-config config docs` ``` Usage: @backstage/cli-module-config config docs @@ -44,7 +44,7 @@ Options: -h, --help ``` -### `cli-module-config config schema` +### `backstage-cli-module-config config schema` ``` Usage: @backstage/cli-module-config config schema @@ -56,7 +56,7 @@ Options: -h, --help ``` -### `cli-module-config config:check` +### `backstage-cli-module-config config:check` ``` Usage: @backstage/cli-module-config config:check @@ -71,7 +71,7 @@ Options: -h, --help ``` -### `cli-module-config config:docs` +### `backstage-cli-module-config config:docs` ``` Usage: @backstage/cli-module-config config:docs @@ -81,7 +81,7 @@ Options: -h, --help ``` -### `cli-module-config config:print` +### `backstage-cli-module-config config:print` ``` Usage: @backstage/cli-module-config config:print @@ -96,7 +96,7 @@ Options: -h, --help ``` -### `cli-module-config config:schema` +### `backstage-cli-module-config config:schema` ``` Usage: @backstage/cli-module-config config:schema diff --git a/packages/cli-module-config/package.json b/packages/cli-module-config/package.json index 4c281dcaa3..bbdf6070a3 100644 --- a/packages/cli-module-config/package.json +++ b/packages/cli-module-config/package.json @@ -48,5 +48,5 @@ "@backstage/cli": "workspace:^", "@types/json-schema": "^7.0.6" }, - "bin": "bin/cli-module-config" + "bin": "bin/backstage-cli-module-config" } diff --git a/packages/cli-module-create-github-app/bin/cli-module-create-github-app b/packages/cli-module-create-github-app/bin/backstage-cli-module-create-github-app similarity index 100% rename from packages/cli-module-create-github-app/bin/cli-module-create-github-app rename to packages/cli-module-create-github-app/bin/backstage-cli-module-create-github-app diff --git a/packages/cli-module-create-github-app/cli-report.md b/packages/cli-module-create-github-app/cli-report.md index a12ea68bf2..7a7f7bb3a2 100644 --- a/packages/cli-module-create-github-app/cli-report.md +++ b/packages/cli-module-create-github-app/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-create-github-app` +### `backstage-cli-module-create-github-app` ``` Usage: @backstage/cli-module-create-github-app [options] [command] @@ -16,7 +16,7 @@ Commands: help [command] ``` -### `cli-module-create-github-app create-github-app` +### `backstage-cli-module-create-github-app create-github-app` ``` Usage: @backstage/cli-module-create-github-app create-github-app diff --git a/packages/cli-module-create-github-app/package.json b/packages/cli-module-create-github-app/package.json index 9b342a4551..2196abc62e 100644 --- a/packages/cli-module-create-github-app/package.json +++ b/packages/cli-module-create-github-app/package.json @@ -48,5 +48,5 @@ "@types/express": "^4.17.6", "@types/fs-extra": "^11.0.0" }, - "bin": "bin/cli-module-create-github-app" + "bin": "bin/backstage-cli-module-create-github-app" } diff --git a/packages/cli-module-info/bin/cli-module-info b/packages/cli-module-info/bin/backstage-cli-module-info similarity index 100% rename from packages/cli-module-info/bin/cli-module-info rename to packages/cli-module-info/bin/backstage-cli-module-info diff --git a/packages/cli-module-info/cli-report.md b/packages/cli-module-info/cli-report.md index f292e46a18..f83583b781 100644 --- a/packages/cli-module-info/cli-report.md +++ b/packages/cli-module-info/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-info` +### `backstage-cli-module-info` ``` Usage: @backstage/cli-module-info [options] [command] @@ -16,7 +16,7 @@ Commands: info ``` -### `cli-module-info info` +### `backstage-cli-module-info info` ``` Usage: @backstage/cli-module-info info diff --git a/packages/cli-module-info/package.json b/packages/cli-module-info/package.json index aafa7908fe..db19b358f4 100644 --- a/packages/cli-module-info/package.json +++ b/packages/cli-module-info/package.json @@ -42,5 +42,5 @@ "@backstage/cli": "workspace:^", "@types/fs-extra": "^11.0.0" }, - "bin": "bin/cli-module-info" + "bin": "bin/backstage-cli-module-info" } diff --git a/packages/cli-module-lint/bin/cli-module-lint b/packages/cli-module-lint/bin/backstage-cli-module-lint similarity index 100% rename from packages/cli-module-lint/bin/cli-module-lint rename to packages/cli-module-lint/bin/backstage-cli-module-lint diff --git a/packages/cli-module-lint/cli-report.md b/packages/cli-module-lint/cli-report.md index c577759e0c..2a9ff6d61f 100644 --- a/packages/cli-module-lint/cli-report.md +++ b/packages/cli-module-lint/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-lint` +### `backstage-cli-module-lint` ``` Usage: @backstage/cli-module-lint [options] [command] @@ -17,7 +17,7 @@ Commands: repo [command] ``` -### `cli-module-lint package` +### `backstage-cli-module-lint package` ``` Usage: @backstage/cli-module-lint package [options] [command] [command] @@ -30,7 +30,7 @@ Commands: lint ``` -### `cli-module-lint package lint` +### `backstage-cli-module-lint package lint` ``` Usage: @backstage/cli-module-lint package lint [directories...] @@ -43,7 +43,7 @@ Options: -h, --help ``` -### `cli-module-lint repo` +### `backstage-cli-module-lint repo` ``` Usage: @backstage/cli-module-lint repo [options] [command] [command] @@ -56,7 +56,7 @@ Commands: lint ``` -### `cli-module-lint repo lint` +### `backstage-cli-module-lint repo lint` ``` Usage: @backstage/cli-module-lint repo lint diff --git a/packages/cli-module-lint/package.json b/packages/cli-module-lint/package.json index e6b9615e39..452e10eeed 100644 --- a/packages/cli-module-lint/package.json +++ b/packages/cli-module-lint/package.json @@ -47,5 +47,5 @@ "@types/fs-extra": "^11.0.0", "@types/shell-quote": "^1.7.5" }, - "bin": "bin/cli-module-lint" + "bin": "bin/backstage-cli-module-lint" } diff --git a/packages/cli-module-maintenance/bin/cli-module-maintenance b/packages/cli-module-maintenance/bin/backstage-cli-module-maintenance similarity index 100% rename from packages/cli-module-maintenance/bin/cli-module-maintenance rename to packages/cli-module-maintenance/bin/backstage-cli-module-maintenance diff --git a/packages/cli-module-maintenance/cli-report.md b/packages/cli-module-maintenance/cli-report.md index 66b9950328..874d9d781d 100644 --- a/packages/cli-module-maintenance/cli-report.md +++ b/packages/cli-module-maintenance/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-maintenance` +### `backstage-cli-module-maintenance` ``` Usage: @backstage/cli-module-maintenance [options] [command] @@ -16,7 +16,7 @@ Commands: repo [command] ``` -### `cli-module-maintenance repo` +### `backstage-cli-module-maintenance repo` ``` Usage: @backstage/cli-module-maintenance repo [options] [command] [command] @@ -30,7 +30,7 @@ Commands: list-deprecations ``` -### `cli-module-maintenance repo fix` +### `backstage-cli-module-maintenance repo fix` ``` Usage: @backstage/cli-module-maintenance repo fix @@ -41,7 +41,7 @@ Options: -h, --help ``` -### `cli-module-maintenance repo list-deprecations` +### `backstage-cli-module-maintenance repo list-deprecations` ``` Usage: @backstage/cli-module-maintenance repo list-deprecations diff --git a/packages/cli-module-maintenance/package.json b/packages/cli-module-maintenance/package.json index 4293beb4ff..24f7a9b70a 100644 --- a/packages/cli-module-maintenance/package.json +++ b/packages/cli-module-maintenance/package.json @@ -43,5 +43,5 @@ "@backstage/cli": "workspace:^", "@types/fs-extra": "^11.0.0" }, - "bin": "bin/cli-module-maintenance" + "bin": "bin/backstage-cli-module-maintenance" } diff --git a/packages/cli-module-migrate/bin/cli-module-migrate b/packages/cli-module-migrate/bin/backstage-cli-module-migrate similarity index 100% rename from packages/cli-module-migrate/bin/cli-module-migrate rename to packages/cli-module-migrate/bin/backstage-cli-module-migrate diff --git a/packages/cli-module-migrate/cli-report.md b/packages/cli-module-migrate/cli-report.md index 06a60cdfaf..f0c29e1edd 100644 --- a/packages/cli-module-migrate/cli-report.md +++ b/packages/cli-module-migrate/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-migrate` +### `backstage-cli-module-migrate` ``` Usage: @backstage/cli-module-migrate [options] [command] @@ -18,7 +18,7 @@ Commands: versions:migrate ``` -### `cli-module-migrate migrate` +### `backstage-cli-module-migrate migrate` ``` Usage: @backstage/cli-module-migrate migrate [options] [command] [command] @@ -35,7 +35,7 @@ Commands: react-router-deps ``` -### `cli-module-migrate migrate package-exports` +### `backstage-cli-module-migrate migrate package-exports` ``` Usage: @backstage/cli-module-migrate migrate package-exports @@ -44,7 +44,7 @@ Options: -h, --help ``` -### `cli-module-migrate migrate package-lint-configs` +### `backstage-cli-module-migrate migrate package-lint-configs` ``` Usage: @backstage/cli-module-migrate migrate package-lint-configs @@ -53,7 +53,7 @@ Options: -h, --help ``` -### `cli-module-migrate migrate package-roles` +### `backstage-cli-module-migrate migrate package-roles` ``` Usage: @backstage/cli-module-migrate migrate package-roles @@ -62,7 +62,7 @@ Options: -h, --help ``` -### `cli-module-migrate migrate package-scripts` +### `backstage-cli-module-migrate migrate package-scripts` ``` Usage: @backstage/cli-module-migrate migrate package-scripts @@ -71,7 +71,7 @@ Options: -h, --help ``` -### `cli-module-migrate migrate react-router-deps` +### `backstage-cli-module-migrate migrate react-router-deps` ``` Usage: @backstage/cli-module-migrate migrate react-router-deps @@ -80,7 +80,7 @@ Options: -h, --help ``` -### `cli-module-migrate versions:bump` +### `backstage-cli-module-migrate versions:bump` ``` Usage: @backstage/cli-module-migrate versions:bump @@ -93,7 +93,7 @@ Options: -h, --help ``` -### `cli-module-migrate versions:migrate` +### `backstage-cli-module-migrate versions:migrate` ``` Usage: @backstage/cli-module-migrate versions:migrate diff --git a/packages/cli-module-migrate/package.json b/packages/cli-module-migrate/package.json index b558cfab19..dfc155fd11 100644 --- a/packages/cli-module-migrate/package.json +++ b/packages/cli-module-migrate/package.json @@ -53,5 +53,5 @@ "@types/semver": "^7", "msw": "^1.0.0" }, - "bin": "bin/cli-module-migrate" + "bin": "bin/backstage-cli-module-migrate" } diff --git a/packages/cli-module-new/bin/cli-module-new b/packages/cli-module-new/bin/backstage-cli-module-new similarity index 100% rename from packages/cli-module-new/bin/cli-module-new rename to packages/cli-module-new/bin/backstage-cli-module-new diff --git a/packages/cli-module-new/cli-report.md b/packages/cli-module-new/cli-report.md index 2c414fc747..a2b4768148 100644 --- a/packages/cli-module-new/cli-report.md +++ b/packages/cli-module-new/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-new` +### `backstage-cli-module-new` ``` Usage: @backstage/cli-module-new [options] [command] @@ -16,7 +16,7 @@ Commands: new ``` -### `cli-module-new new` +### `backstage-cli-module-new new` ``` Usage: @backstage/cli-module-new new diff --git a/packages/cli-module-new/package.json b/packages/cli-module-new/package.json index bd056c507c..9ca1664f7a 100644 --- a/packages/cli-module-new/package.json +++ b/packages/cli-module-new/package.json @@ -58,5 +58,5 @@ "@types/lodash": "^4.14.151", "@types/recursive-readdir": "^2.2.0" }, - "bin": "bin/cli-module-new" + "bin": "bin/backstage-cli-module-new" } diff --git a/packages/cli-module-test-jest/bin/cli-module-test-jest b/packages/cli-module-test-jest/bin/backstage-cli-module-test-jest similarity index 100% rename from packages/cli-module-test-jest/bin/cli-module-test-jest rename to packages/cli-module-test-jest/bin/backstage-cli-module-test-jest diff --git a/packages/cli-module-test-jest/cli-report.md b/packages/cli-module-test-jest/cli-report.md index ca1d390ed7..00523eb8cf 100644 --- a/packages/cli-module-test-jest/cli-report.md +++ b/packages/cli-module-test-jest/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-test-jest` +### `backstage-cli-module-test-jest` ``` Usage: @backstage/cli-module-test-jest [options] [command] @@ -17,7 +17,7 @@ Commands: repo [command] ``` -### `cli-module-test-jest package` +### `backstage-cli-module-test-jest package` ``` Usage: @backstage/cli-module-test-jest package [options] [command] [command] @@ -30,10 +30,10 @@ Commands: test ``` -### `cli-module-test-jest package test` +### `backstage-cli-module-test-jest package test` ``` -Usage: cli-module-test-jest [--config=] [TestPathPatterns] +Usage: backstage-cli-module-test-jest [--config=] Options: --all @@ -143,7 +143,7 @@ Options: -w, --maxWorkers ``` -### `cli-module-test-jest repo` +### `backstage-cli-module-test-jest repo` ``` Usage: @backstage/cli-module-test-jest repo [options] [command] [command] @@ -156,7 +156,7 @@ Commands: test ``` -### `cli-module-test-jest repo test` +### `backstage-cli-module-test-jest repo test` ``` Usage: @backstage/cli-module-test-jest repo test diff --git a/packages/cli-module-test-jest/package.json b/packages/cli-module-test-jest/package.json index 36dd8fafdf..6d7811f484 100644 --- a/packages/cli-module-test-jest/package.json +++ b/packages/cli-module-test-jest/package.json @@ -65,5 +65,5 @@ "optional": true } }, - "bin": "bin/cli-module-test-jest" + "bin": "bin/backstage-cli-module-test-jest" } diff --git a/packages/cli-module-translations/bin/cli-module-translations b/packages/cli-module-translations/bin/backstage-cli-module-translations similarity index 100% rename from packages/cli-module-translations/bin/cli-module-translations rename to packages/cli-module-translations/bin/backstage-cli-module-translations diff --git a/packages/cli-module-translations/cli-report.md b/packages/cli-module-translations/cli-report.md index 9b2d5ef3b4..bf2ff28001 100644 --- a/packages/cli-module-translations/cli-report.md +++ b/packages/cli-module-translations/cli-report.md @@ -2,7 +2,7 @@ > Do not edit this file. It is a report generated by `yarn build:api-reports` -### `cli-module-translations` +### `backstage-cli-module-translations` ``` Usage: @backstage/cli-module-translations [options] [command] @@ -16,7 +16,7 @@ Commands: translations [command] ``` -### `cli-module-translations translations` +### `backstage-cli-module-translations translations` ``` Usage: @backstage/cli-module-translations translations [options] [command] [command] @@ -30,7 +30,7 @@ Commands: import ``` -### `cli-module-translations translations export` +### `backstage-cli-module-translations translations export` ``` Usage: @backstage/cli-module-translations translations export @@ -41,7 +41,7 @@ Options: -h, --help ``` -### `cli-module-translations translations import` +### `backstage-cli-module-translations translations import` ``` Usage: @backstage/cli-module-translations translations import diff --git a/packages/cli-module-translations/package.json b/packages/cli-module-translations/package.json index 0bb3714889..86ef2b7ca4 100644 --- a/packages/cli-module-translations/package.json +++ b/packages/cli-module-translations/package.json @@ -42,5 +42,5 @@ "@backstage/cli": "workspace:^", "@types/fs-extra": "^11.0.0" }, - "bin": "bin/cli-module-translations" + "bin": "bin/backstage-cli-module-translations" } diff --git a/yarn.lock b/yarn.lock index 275cf38895..1c4ba53f5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2843,7 +2843,7 @@ __metadata: keytar: optional: true bin: - cli-module-auth: bin/cli-module-auth + cli-module-auth: bin/backstage-cli-module-auth languageName: unknown linkType: soft @@ -2918,7 +2918,7 @@ __metadata: yml-loader: "npm:^2.1.0" yn: "npm:^4.0.0" bin: - cli-module-build: bin/cli-module-build + cli-module-build: bin/backstage-cli-module-build languageName: unknown linkType: soft @@ -2940,7 +2940,7 @@ __metadata: react-dev-utils: "npm:^12.0.0-next.60" yaml: "npm:^2.0.0" bin: - cli-module-config: bin/cli-module-config + cli-module-config: bin/backstage-cli-module-config languageName: unknown linkType: soft @@ -2962,7 +2962,7 @@ __metadata: react-dev-utils: "npm:^12.0.0-next.60" yaml: "npm:^2.0.0" bin: - cli-module-create-github-app: bin/cli-module-create-github-app + cli-module-create-github-app: bin/backstage-cli-module-create-github-app languageName: unknown linkType: soft @@ -2978,7 +2978,7 @@ __metadata: fs-extra: "npm:^11.2.0" minimatch: "npm:^10.2.1" bin: - cli-module-info: bin/cli-module-info + cli-module-info: bin/backstage-cli-module-info languageName: unknown linkType: soft @@ -2999,7 +2999,7 @@ __metadata: globby: "npm:^11.1.0" shell-quote: "npm:^1.8.1" bin: - cli-module-lint: bin/cli-module-lint + cli-module-lint: bin/backstage-cli-module-lint languageName: unknown linkType: soft @@ -3016,7 +3016,7 @@ __metadata: eslint: "npm:^8.6.0" fs-extra: "npm:^11.2.0" bin: - cli-module-maintenance: bin/cli-module-maintenance + cli-module-maintenance: bin/backstage-cli-module-maintenance languageName: unknown linkType: soft @@ -3043,7 +3043,7 @@ __metadata: replace-in-file: "npm:^7.1.0" semver: "npm:^7.5.3" bin: - cli-module-migrate: bin/cli-module-migrate + cli-module-migrate: bin/backstage-cli-module-migrate languageName: unknown linkType: soft @@ -3075,7 +3075,7 @@ __metadata: zod: "npm:^3.25.76" zod-validation-error: "npm:^4.0.2" bin: - cli-module-new: bin/cli-module-new + cli-module-new: bin/backstage-cli-module-new languageName: unknown linkType: soft @@ -3108,7 +3108,7 @@ __metadata: jsdom: optional: true bin: - cli-module-test-jest: bin/cli-module-test-jest + cli-module-test-jest: bin/backstage-cli-module-test-jest languageName: unknown linkType: soft @@ -3124,7 +3124,7 @@ __metadata: fs-extra: "npm:^11.2.0" ts-morph: "npm:^24.0.0" bin: - cli-module-translations: bin/cli-module-translations + cli-module-translations: bin/backstage-cli-module-translations languageName: unknown linkType: soft From 4d081452b14eb297ef1c1c78576ee47ecc2784b6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 12:55:22 +0100 Subject: [PATCH 42/45] Address review feedback from freben - Use cli-defaults instead of listing individual CLI modules in create-app template and root package.json - Move nodeTransform config files from cli-module-build to cli-node to avoid cross-module direct imports - Rename cli-module-create-github-app to cli-module-github - Start createCliModule init chain with Promise.resolve() - Deduplicate exitWithError in runCliModule.ts - Extract shared isCommandNodeHidden to @internal/cli - Add explanatory comment for fromArray deduplication field - Restore error for cli role packages missing bin in runCliExtraction Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .changeset/cli-discover-modules.md | 2 +- .changeset/introduce-cli-modules.md | 2 +- package.json | 12 +---- packages/cli-defaults/README.md | 26 +++++------ packages/cli-defaults/package.json | 2 +- packages/cli-defaults/src/index.ts | 4 +- .../cli-internal/src/InternalCommandNode.ts | 14 ++++++ packages/cli-internal/src/index.ts | 1 + .../bin/backstage-cli-module-auth | 2 +- .../bin/backstage-cli-module-build | 2 +- packages/cli-module-build/package.json | 1 - .../src/lib/runner/runBackend.ts | 7 ++- .../src/tests/transforms/transforms.test.ts | 4 +- .../bin/backstage-cli-module-config | 2 +- .../cli-report.md | 26 ----------- .../.eslintrc.js | 0 .../README.md | 2 +- .../bin/backstage-cli-module-github} | 2 +- .../catalog-info.yaml | 4 +- packages/cli-module-github/cli-report.md | 26 +++++++++++ .../package.json | 6 +-- .../report.api.md | 2 +- .../src/cli.ts | 0 .../GithubCreateAppServer.ts | 0 .../src/commands/create-github-app/index.ts | 0 .../src/index.ts | 0 .../bin/backstage-cli-module-info | 2 +- .../bin/backstage-cli-module-lint | 2 +- .../bin/backstage-cli-module-maintenance | 2 +- .../bin/backstage-cli-module-migrate | 2 +- .../bin/backstage-cli-module-new | 2 +- .../bin/backstage-cli-module-test-jest | 2 +- .../bin/backstage-cli-module-translations | 2 +- packages/cli-node/.eslintrc.js | 20 ++++++++- .../config/nodeTransform.cjs | 0 .../config/nodeTransformHooks.mjs | 0 packages/cli-node/package.json | 5 ++- .../src/cli-module/createCliModule.ts | 4 +- .../cli-node/src/cli-module/runCliModule.ts | 20 +++------ packages/cli/config/nodeTransform.cjs | 4 +- packages/cli/config/nodeTransformHooks.mjs | 2 +- packages/cli/src/wiring/CliInitializer.ts | 19 ++++---- packages/create-app/src/lib/tasks.test.ts | 11 ----- packages/create-app/src/lib/versions.ts | 22 --------- .../templates/next-app/package.json.hbs | 12 +---- .../cli-reports/runCliExtraction.ts | 5 +++ yarn.lock | 45 ++++++++----------- 47 files changed, 147 insertions(+), 185 deletions(-) delete mode 100644 packages/cli-module-create-github-app/cli-report.md rename packages/{cli-module-create-github-app => cli-module-github}/.eslintrc.js (100%) rename packages/{cli-module-create-github-app => cli-module-github}/README.md (92%) rename packages/{cli-module-create-github-app/bin/backstage-cli-module-create-github-app => cli-module-github/bin/backstage-cli-module-github} (94%) rename packages/{cli-module-create-github-app => cli-module-github}/catalog-info.yaml (66%) create mode 100644 packages/cli-module-github/cli-report.md rename packages/{cli-module-create-github-app => cli-module-github}/package.json (88%) rename packages/{cli-module-create-github-app => cli-module-github}/report.api.md (81%) rename packages/{cli-module-create-github-app => cli-module-github}/src/cli.ts (100%) rename packages/{cli-module-create-github-app => cli-module-github}/src/commands/create-github-app/GithubCreateAppServer.ts (100%) rename packages/{cli-module-create-github-app => cli-module-github}/src/commands/create-github-app/index.ts (100%) rename packages/{cli-module-create-github-app => cli-module-github}/src/index.ts (100%) rename packages/{cli-module-build => cli-node}/config/nodeTransform.cjs (100%) rename packages/{cli-module-build => cli-node}/config/nodeTransformHooks.mjs (100%) diff --git a/.changeset/cli-discover-modules.md b/.changeset/cli-discover-modules.md index 751facdf1d..dac5f73f75 100644 --- a/.changeset/cli-discover-modules.md +++ b/.changeset/cli-discover-modules.md @@ -28,7 +28,7 @@ For fine-grained control you can instead install individual CLI modules: "@backstage/cli-module-auth": "backstage:^", "@backstage/cli-module-build": "backstage:^", "@backstage/cli-module-config": "backstage:^", - "@backstage/cli-module-create-github-app": "backstage:^", + "@backstage/cli-module-github": "backstage:^", "@backstage/cli-module-info": "backstage:^", "@backstage/cli-module-lint": "backstage:^", "@backstage/cli-module-maintenance": "backstage:^", diff --git a/.changeset/introduce-cli-modules.md b/.changeset/introduce-cli-modules.md index a69df9164b..7381742621 100644 --- a/.changeset/introduce-cli-modules.md +++ b/.changeset/introduce-cli-modules.md @@ -2,7 +2,7 @@ '@backstage/cli-module-auth': minor '@backstage/cli-module-build': minor '@backstage/cli-module-config': minor -'@backstage/cli-module-create-github-app': minor +'@backstage/cli-module-github': minor '@backstage/cli-module-info': minor '@backstage/cli-module-lint': minor '@backstage/cli-module-maintenance': minor diff --git a/package.json b/package.json index c443b8aa81..c89dcefce6 100644 --- a/package.json +++ b/package.json @@ -125,17 +125,7 @@ }, "devDependencies": { "@backstage/cli": "workspace:*", - "@backstage/cli-module-auth": "workspace:*", - "@backstage/cli-module-build": "workspace:*", - "@backstage/cli-module-config": "workspace:*", - "@backstage/cli-module-create-github-app": "workspace:*", - "@backstage/cli-module-info": "workspace:*", - "@backstage/cli-module-lint": "workspace:*", - "@backstage/cli-module-maintenance": "workspace:*", - "@backstage/cli-module-migrate": "workspace:*", - "@backstage/cli-module-new": "workspace:*", - "@backstage/cli-module-test-jest": "workspace:*", - "@backstage/cli-module-translations": "workspace:*", + "@backstage/cli-defaults": "workspace:*", "@backstage/codemods": "workspace:*", "@backstage/create-app": "workspace:*", "@backstage/e2e-test-utils": "workspace:*", diff --git a/packages/cli-defaults/README.md b/packages/cli-defaults/README.md index fa75c322df..2066aa1e35 100644 --- a/packages/cli-defaults/README.md +++ b/packages/cli-defaults/README.md @@ -4,19 +4,19 @@ The default set of CLI modules for the Backstage CLI. Installing this single pac ## Included Modules -| Module | Description | -| :--------------------------------------------------------------------------- | :--------------------------------------- | -| [`@backstage/cli-module-auth`](../cli-module-auth) | Authentication commands | -| [`@backstage/cli-module-build`](../cli-module-build) | Build, start, and packaging commands | -| [`@backstage/cli-module-config`](../cli-module-config) | Configuration inspection commands | -| [`@backstage/cli-module-create-github-app`](../cli-module-create-github-app) | GitHub App creation | -| [`@backstage/cli-module-info`](../cli-module-info) | Environment and dependency info | -| [`@backstage/cli-module-lint`](../cli-module-lint) | Linting commands | -| [`@backstage/cli-module-maintenance`](../cli-module-maintenance) | Repository maintenance commands | -| [`@backstage/cli-module-migrate`](../cli-module-migrate) | Migration and version management | -| [`@backstage/cli-module-new`](../cli-module-new) | Scaffolding for new plugins and packages | -| [`@backstage/cli-module-test-jest`](../cli-module-test-jest) | Jest-based testing commands | -| [`@backstage/cli-module-translations`](../cli-module-translations) | Translation management commands | +| Module | Description | +| :----------------------------------------------------------------- | :--------------------------------------- | +| [`@backstage/cli-module-auth`](../cli-module-auth) | Authentication commands | +| [`@backstage/cli-module-build`](../cli-module-build) | Build, start, and packaging commands | +| [`@backstage/cli-module-config`](../cli-module-config) | Configuration inspection commands | +| [`@backstage/cli-module-github`](../cli-module-github) | GitHub App creation | +| [`@backstage/cli-module-info`](../cli-module-info) | Environment and dependency info | +| [`@backstage/cli-module-lint`](../cli-module-lint) | Linting commands | +| [`@backstage/cli-module-maintenance`](../cli-module-maintenance) | Repository maintenance commands | +| [`@backstage/cli-module-migrate`](../cli-module-migrate) | Migration and version management | +| [`@backstage/cli-module-new`](../cli-module-new) | Scaffolding for new plugins and packages | +| [`@backstage/cli-module-test-jest`](../cli-module-test-jest) | Jest-based testing commands | +| [`@backstage/cli-module-translations`](../cli-module-translations) | Translation management commands | For fine-grained control over which CLI commands are available, you can install individual modules instead. diff --git a/packages/cli-defaults/package.json b/packages/cli-defaults/package.json index 587e54cfe9..8a065fd4d7 100644 --- a/packages/cli-defaults/package.json +++ b/packages/cli-defaults/package.json @@ -33,7 +33,7 @@ "@backstage/cli-module-auth": "workspace:^", "@backstage/cli-module-build": "workspace:^", "@backstage/cli-module-config": "workspace:^", - "@backstage/cli-module-create-github-app": "workspace:^", + "@backstage/cli-module-github": "workspace:^", "@backstage/cli-module-info": "workspace:^", "@backstage/cli-module-lint": "workspace:^", "@backstage/cli-module-maintenance": "workspace:^", diff --git a/packages/cli-defaults/src/index.ts b/packages/cli-defaults/src/index.ts index 0126d0c074..dd7aed0c70 100644 --- a/packages/cli-defaults/src/index.ts +++ b/packages/cli-defaults/src/index.ts @@ -16,7 +16,7 @@ import auth from '@backstage/cli-module-auth'; import build from '@backstage/cli-module-build'; import config from '@backstage/cli-module-config'; -import createGithubApp from '@backstage/cli-module-create-github-app'; +import github from '@backstage/cli-module-github'; import info from '@backstage/cli-module-info'; import lint from '@backstage/cli-module-lint'; import maintenance from '@backstage/cli-module-maintenance'; @@ -34,7 +34,7 @@ export default [ auth, build, config, - createGithubApp, + github, info, lint, maintenance, diff --git a/packages/cli-internal/src/InternalCommandNode.ts b/packages/cli-internal/src/InternalCommandNode.ts index bfa1f90baa..233e9128cb 100644 --- a/packages/cli-internal/src/InternalCommandNode.ts +++ b/packages/cli-internal/src/InternalCommandNode.ts @@ -53,3 +53,17 @@ export const OpaqueCommandLeafNode = OpaqueType.create<{ type: '@backstage/CommandLeafNode', versions: ['v1'], }); + +/** + * Checks whether a command node should be hidden from help output. + * Leaf nodes are hidden if they are deprecated or experimental. + * Tree nodes are hidden if all of their children are hidden. + */ +export function isCommandNodeHidden(node: CommandNode): boolean { + if (OpaqueCommandLeafNode.isType(node)) { + const { command } = OpaqueCommandLeafNode.toInternal(node); + return !!command.deprecated || !!command.experimental; + } + const { children } = OpaqueCommandTreeNode.toInternal(node); + return children.every(child => isCommandNodeHidden(child)); +} diff --git a/packages/cli-internal/src/index.ts b/packages/cli-internal/src/index.ts index 68b5affe64..0e69d45032 100644 --- a/packages/cli-internal/src/index.ts +++ b/packages/cli-internal/src/index.ts @@ -23,4 +23,5 @@ export type { export { OpaqueCommandTreeNode, OpaqueCommandLeafNode, + isCommandNodeHidden, } from './InternalCommandNode'; diff --git a/packages/cli-module-auth/bin/backstage-cli-module-auth b/packages/cli-module-auth/bin/backstage-cli-module-auth index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-auth/bin/backstage-cli-module-auth +++ b/packages/cli-module-auth/bin/backstage-cli-module-auth @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-build/bin/backstage-cli-module-build b/packages/cli-module-build/bin/backstage-cli-module-build index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-build/bin/backstage-cli-module-build +++ b/packages/cli-module-build/bin/backstage-cli-module-build @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-build/package.json b/packages/cli-module-build/package.json index 27f4fd3903..d13fa4bac0 100644 --- a/packages/cli-module-build/package.json +++ b/packages/cli-module-build/package.json @@ -72,7 +72,6 @@ "node-stdlib-browser": "^1.3.1", "npm-packlist": "^5.0.0", "p-queue": "^6.6.2", - "pirates": "^4.0.6", "postcss": "^8.1.0", "postcss-import": "^16.1.0", "process": "^0.11.10", diff --git a/packages/cli-module-build/src/lib/runner/runBackend.ts b/packages/cli-module-build/src/lib/runner/runBackend.ts index 73c3fe08c7..86c249e8be 100644 --- a/packages/cli-module-build/src/lib/runner/runBackend.ts +++ b/packages/cli-module-build/src/lib/runner/runBackend.ts @@ -21,16 +21,15 @@ import { IpcServer, ServerDataStore } from '../ipc'; import debounce from 'lodash/debounce'; import { fileURLToPath } from 'node:url'; import { isAbsolute as isAbsolutePath } from 'node:path'; -import { findOwnPaths, targetPaths } from '@backstage/cli-common'; +import { targetPaths } from '@backstage/cli-common'; import spawn from 'cross-spawn'; const loaderArgs = [ '--enable-source-maps', '--require', - /* eslint-disable-next-line no-restricted-syntax */ - findOwnPaths(__dirname).resolve('config/nodeTransform.cjs'), - // TODO: Support modules, although there's currently no way to load them since import() is transpiled tp require() + require.resolve('@backstage/cli-node/config/nodeTransform.cjs'), + // TODO: Support modules, although there's currently no way to load them since import() is transpiled to require() ]; export type RunBackendOptions = { diff --git a/packages/cli-module-build/src/tests/transforms/transforms.test.ts b/packages/cli-module-build/src/tests/transforms/transforms.test.ts index 40f40fac2d..71ee03df76 100644 --- a/packages/cli-module-build/src/tests/transforms/transforms.test.ts +++ b/packages/cli-module-build/src/tests/transforms/transforms.test.ts @@ -16,7 +16,6 @@ import { execFileSync } from 'node:child_process'; import { resolve as resolvePath } from 'node:path'; -import { findOwnPaths } from '@backstage/cli-common'; import { Output, buildPackage } from '../../lib/builder'; const exportValues = { @@ -56,8 +55,7 @@ function loadFixture(fixture: string) { 'node', [ '--import', - /* eslint-disable-next-line no-restricted-syntax */ - findOwnPaths(__dirname).resolve('config/nodeTransform.cjs'), + require.resolve('@backstage/cli-node/config/nodeTransform.cjs'), resolvePath(__dirname, `__fixtures__/${fixture}`), ], { encoding: 'utf8' }, diff --git a/packages/cli-module-config/bin/backstage-cli-module-config b/packages/cli-module-config/bin/backstage-cli-module-config index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-config/bin/backstage-cli-module-config +++ b/packages/cli-module-config/bin/backstage-cli-module-config @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-create-github-app/cli-report.md b/packages/cli-module-create-github-app/cli-report.md deleted file mode 100644 index 7a7f7bb3a2..0000000000 --- a/packages/cli-module-create-github-app/cli-report.md +++ /dev/null @@ -1,26 +0,0 @@ -## CLI Report file for "@backstage/cli-module-create-github-app" - -> Do not edit this file. It is a report generated by `yarn build:api-reports` - -### `backstage-cli-module-create-github-app` - -``` -Usage: @backstage/cli-module-create-github-app [options] [command] - -Options: - -V, --version - -h, --help - -Commands: - create-github-app - help [command] -``` - -### `backstage-cli-module-create-github-app create-github-app` - -``` -Usage: @backstage/cli-module-create-github-app create-github-app - -Options: - -h, --help -``` diff --git a/packages/cli-module-create-github-app/.eslintrc.js b/packages/cli-module-github/.eslintrc.js similarity index 100% rename from packages/cli-module-create-github-app/.eslintrc.js rename to packages/cli-module-github/.eslintrc.js diff --git a/packages/cli-module-create-github-app/README.md b/packages/cli-module-github/README.md similarity index 92% rename from packages/cli-module-create-github-app/README.md rename to packages/cli-module-github/README.md index b10272ab02..6c38376901 100644 --- a/packages/cli-module-create-github-app/README.md +++ b/packages/cli-module-github/README.md @@ -1,4 +1,4 @@ -# @backstage/cli-module-create-github-app +# @backstage/cli-module-github CLI module that provides the `create-github-app` command for the Backstage CLI, used to create a new GitHub App in your organization for use with Backstage. diff --git a/packages/cli-module-create-github-app/bin/backstage-cli-module-create-github-app b/packages/cli-module-github/bin/backstage-cli-module-github similarity index 94% rename from packages/cli-module-create-github-app/bin/backstage-cli-module-create-github-app rename to packages/cli-module-github/bin/backstage-cli-module-github index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-create-github-app/bin/backstage-cli-module-create-github-app +++ b/packages/cli-module-github/bin/backstage-cli-module-github @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-create-github-app/catalog-info.yaml b/packages/cli-module-github/catalog-info.yaml similarity index 66% rename from packages/cli-module-create-github-app/catalog-info.yaml rename to packages/cli-module-github/catalog-info.yaml index 66e59c5a27..b694da6f17 100644 --- a/packages/cli-module-create-github-app/catalog-info.yaml +++ b/packages/cli-module-github/catalog-info.yaml @@ -1,8 +1,8 @@ apiVersion: backstage.io/v1alpha1 kind: Component metadata: - name: backstage-cli-module-create-github-app - title: '@backstage/cli-module-create-github-app' + name: backstage-cli-module-github + title: '@backstage/cli-module-github' description: CLI module for Backstage CLI spec: lifecycle: experimental diff --git a/packages/cli-module-github/cli-report.md b/packages/cli-module-github/cli-report.md new file mode 100644 index 0000000000..c606ac5988 --- /dev/null +++ b/packages/cli-module-github/cli-report.md @@ -0,0 +1,26 @@ +## CLI Report file for "@backstage/cli-module-github" + +> Do not edit this file. It is a report generated by `yarn build:api-reports` + +### `backstage-cli-module-github` + +``` +Usage: @backstage/cli-module-github [options] [command] + +Options: + -V, --version + -h, --help + +Commands: + create-github-app + help [command] +``` + +### `backstage-cli-module-github create-github-app` + +``` +Usage: @backstage/cli-module-github create-github-app + +Options: + -h, --help +``` diff --git a/packages/cli-module-create-github-app/package.json b/packages/cli-module-github/package.json similarity index 88% rename from packages/cli-module-create-github-app/package.json rename to packages/cli-module-github/package.json index 2196abc62e..1e8ca4fe6a 100644 --- a/packages/cli-module-create-github-app/package.json +++ b/packages/cli-module-github/package.json @@ -1,5 +1,5 @@ { - "name": "@backstage/cli-module-create-github-app", + "name": "@backstage/cli-module-github", "version": "0.0.0", "description": "CLI module for Backstage CLI", "backstage": { @@ -14,7 +14,7 @@ "repository": { "type": "git", "url": "https://github.com/backstage/backstage", - "directory": "packages/cli-module-create-github-app" + "directory": "packages/cli-module-github" }, "license": "Apache-2.0", "main": "src/index.ts", @@ -48,5 +48,5 @@ "@types/express": "^4.17.6", "@types/fs-extra": "^11.0.0" }, - "bin": "bin/backstage-cli-module-create-github-app" + "bin": "bin/backstage-cli-module-github" } diff --git a/packages/cli-module-create-github-app/report.api.md b/packages/cli-module-github/report.api.md similarity index 81% rename from packages/cli-module-create-github-app/report.api.md rename to packages/cli-module-github/report.api.md index 16ff642c69..c389a88b5f 100644 --- a/packages/cli-module-create-github-app/report.api.md +++ b/packages/cli-module-github/report.api.md @@ -1,4 +1,4 @@ -## API Report File for "@backstage/cli-module-create-github-app" +## API Report File for "@backstage/cli-module-github" > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). diff --git a/packages/cli-module-create-github-app/src/cli.ts b/packages/cli-module-github/src/cli.ts similarity index 100% rename from packages/cli-module-create-github-app/src/cli.ts rename to packages/cli-module-github/src/cli.ts diff --git a/packages/cli-module-create-github-app/src/commands/create-github-app/GithubCreateAppServer.ts b/packages/cli-module-github/src/commands/create-github-app/GithubCreateAppServer.ts similarity index 100% rename from packages/cli-module-create-github-app/src/commands/create-github-app/GithubCreateAppServer.ts rename to packages/cli-module-github/src/commands/create-github-app/GithubCreateAppServer.ts diff --git a/packages/cli-module-create-github-app/src/commands/create-github-app/index.ts b/packages/cli-module-github/src/commands/create-github-app/index.ts similarity index 100% rename from packages/cli-module-create-github-app/src/commands/create-github-app/index.ts rename to packages/cli-module-github/src/commands/create-github-app/index.ts diff --git a/packages/cli-module-create-github-app/src/index.ts b/packages/cli-module-github/src/index.ts similarity index 100% rename from packages/cli-module-create-github-app/src/index.ts rename to packages/cli-module-github/src/index.ts diff --git a/packages/cli-module-info/bin/backstage-cli-module-info b/packages/cli-module-info/bin/backstage-cli-module-info index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-info/bin/backstage-cli-module-info +++ b/packages/cli-module-info/bin/backstage-cli-module-info @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-lint/bin/backstage-cli-module-lint b/packages/cli-module-lint/bin/backstage-cli-module-lint index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-lint/bin/backstage-cli-module-lint +++ b/packages/cli-module-lint/bin/backstage-cli-module-lint @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-maintenance/bin/backstage-cli-module-maintenance b/packages/cli-module-maintenance/bin/backstage-cli-module-maintenance index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-maintenance/bin/backstage-cli-module-maintenance +++ b/packages/cli-module-maintenance/bin/backstage-cli-module-maintenance @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-migrate/bin/backstage-cli-module-migrate b/packages/cli-module-migrate/bin/backstage-cli-module-migrate index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-migrate/bin/backstage-cli-module-migrate +++ b/packages/cli-module-migrate/bin/backstage-cli-module-migrate @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-new/bin/backstage-cli-module-new b/packages/cli-module-new/bin/backstage-cli-module-new index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-new/bin/backstage-cli-module-new +++ b/packages/cli-module-new/bin/backstage-cli-module-new @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-test-jest/bin/backstage-cli-module-test-jest b/packages/cli-module-test-jest/bin/backstage-cli-module-test-jest index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-test-jest/bin/backstage-cli-module-test-jest +++ b/packages/cli-module-test-jest/bin/backstage-cli-module-test-jest @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-module-translations/bin/backstage-cli-module-translations b/packages/cli-module-translations/bin/backstage-cli-module-translations index 533974f6a9..885c06db9f 100755 --- a/packages/cli-module-translations/bin/backstage-cli-module-translations +++ b/packages/cli-module-translations/bin/backstage-cli-module-translations @@ -28,6 +28,6 @@ if (!isLocal) { const pkg = require('../package.json'); runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); } else { - require('@backstage/cli/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); require('../src/cli'); } diff --git a/packages/cli-node/.eslintrc.js b/packages/cli-node/.eslintrc.js index e2a53a6ad2..7e7c302633 100644 --- a/packages/cli-node/.eslintrc.js +++ b/packages/cli-node/.eslintrc.js @@ -1 +1,19 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +/* + * Copyright 2026 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. + */ +module.exports = { + ...require('@backstage/cli/config/eslint-factory')(__dirname), + ignorePatterns: ['config/**'], +}; diff --git a/packages/cli-module-build/config/nodeTransform.cjs b/packages/cli-node/config/nodeTransform.cjs similarity index 100% rename from packages/cli-module-build/config/nodeTransform.cjs rename to packages/cli-node/config/nodeTransform.cjs diff --git a/packages/cli-module-build/config/nodeTransformHooks.mjs b/packages/cli-node/config/nodeTransformHooks.mjs similarity index 100% rename from packages/cli-module-build/config/nodeTransformHooks.mjs rename to packages/cli-node/config/nodeTransformHooks.mjs diff --git a/packages/cli-node/package.json b/packages/cli-node/package.json index 95322ad2f0..e266088176 100644 --- a/packages/cli-node/package.json +++ b/packages/cli-node/package.json @@ -20,7 +20,8 @@ "main": "src/index.ts", "types": "src/index.ts", "files": [ - "dist" + "dist", + "config" ], "scripts": { "build": "backstage-cli package build", @@ -35,11 +36,13 @@ "@backstage/errors": "workspace:^", "@backstage/types": "workspace:^", "@manypkg/get-packages": "^1.1.3", + "@swc/core": "^1.15.6", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "^3.0.0", "chalk": "^4.0.0", "commander": "^12.0.0", "fs-extra": "^11.2.0", + "pirates": "^4.0.6", "semver": "^7.5.3", "yaml": "^2.0.0", "zod": "^3.25.76" diff --git a/packages/cli-node/src/cli-module/createCliModule.ts b/packages/cli-node/src/cli-module/createCliModule.ts index 7d52e9bf43..b2facc3a67 100644 --- a/packages/cli-node/src/cli-module/createCliModule.ts +++ b/packages/cli-node/src/cli-module/createCliModule.ts @@ -62,8 +62,8 @@ export function createCliModule(options: { } const commands: CliCommand[] = []; - const commandsPromise = options - .init({ addCommand: command => commands.push(command) }) + const commandsPromise = Promise.resolve() + .then(() => options.init({ addCommand: command => commands.push(command) })) .then(() => commands); return OpaqueCliModule.createInstance('v1', { diff --git a/packages/cli-node/src/cli-module/runCliModule.ts b/packages/cli-node/src/cli-module/runCliModule.ts index 84893f0cac..0dc40e4c33 100644 --- a/packages/cli-node/src/cli-module/runCliModule.ts +++ b/packages/cli-node/src/cli-module/runCliModule.ts @@ -18,6 +18,7 @@ import { OpaqueCliModule, OpaqueCommandTreeNode, OpaqueCommandLeafNode, + isCommandNodeHidden, } from '@internal/cli'; import type { CommandNode } from '@internal/cli'; import { Command } from 'commander'; @@ -25,15 +26,6 @@ import chalk from 'chalk'; import { isError, stringifyError } from '@backstage/errors'; import type { CliModule, CliCommand } from './types'; -function isCommandHidden(node: CommandNode): boolean { - if (OpaqueCommandLeafNode.isType(node)) { - const { command } = OpaqueCommandLeafNode.toInternal(node); - return !!command.deprecated || !!command.experimental; - } - const { children } = OpaqueCommandTreeNode.toInternal(node); - return children.every(child => isCommandHidden(child)); -} - function buildCommandGraph(commands: ReadonlyArray): CommandNode[] { const graph: CommandNode[] = []; @@ -70,13 +62,11 @@ function buildCommandGraph(commands: ReadonlyArray): CommandNode[] { } function exitWithError(error: unknown): never { - if (!isError(error)) { - process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`); - process.exit(1); - } process.stderr.write(`\n${chalk.red(stringifyError(error))}\n\n`); process.exit( - 'code' in error && typeof error.code === 'number' ? error.code : 1, + isError(error) && 'code' in error && typeof error.code === 'number' + ? error.code + : 1, ); } @@ -94,7 +84,7 @@ function registerCommands( const internal = OpaqueCommandTreeNode.toInternal(node); const treeParser = argParser .command(`${internal.name} [command]`, { - hidden: isCommandHidden(node), + hidden: isCommandNodeHidden(node), }) .description(internal.name); diff --git a/packages/cli/config/nodeTransform.cjs b/packages/cli/config/nodeTransform.cjs index 83815ebea9..c6866b2964 100644 --- a/packages/cli/config/nodeTransform.cjs +++ b/packages/cli/config/nodeTransform.cjs @@ -15,11 +15,11 @@ */ try { - require('@backstage/cli-module-build/config/nodeTransform.cjs'); + require('@backstage/cli-node/config/nodeTransform.cjs'); } catch (e) { if (e.code === 'MODULE_NOT_FOUND') { throw new Error( - '@backstage/cli-module-build is required to use the node transform. ' + + '@backstage/cli-node is required to use the node transform. ' + 'Please install it as a dependency.', ); } diff --git a/packages/cli/config/nodeTransformHooks.mjs b/packages/cli/config/nodeTransformHooks.mjs index 9fe9b327b5..274e24ed39 100644 --- a/packages/cli/config/nodeTransformHooks.mjs +++ b/packages/cli/config/nodeTransformHooks.mjs @@ -17,4 +17,4 @@ export { resolve, load, -} from '@backstage/cli-module-build/config/nodeTransformHooks.mjs'; +} from '@backstage/cli-node/config/nodeTransformHooks.mjs'; diff --git a/packages/cli/src/wiring/CliInitializer.ts b/packages/cli/src/wiring/CliInitializer.ts index e2c46cf99b..adbdfbe517 100644 --- a/packages/cli/src/wiring/CliInitializer.ts +++ b/packages/cli/src/wiring/CliInitializer.ts @@ -19,8 +19,8 @@ import { OpaqueCliModule, OpaqueCommandTreeNode, OpaqueCommandLeafNode, + isCommandNodeHidden, } from '@internal/cli'; -import type { CommandNode } from '@internal/cli'; import type { CliModule } from '@backstage/cli-node'; import { Command } from 'commander'; import { version } from './version'; @@ -29,15 +29,6 @@ import { exitWithError } from './errors'; import { ForwardedError } from '@backstage/errors'; import { isPromise } from 'node:util/types'; -function isNodeHidden(node: CommandNode): boolean { - if (OpaqueCommandLeafNode.isType(node)) { - const { command } = OpaqueCommandLeafNode.toInternal(node); - return !!command.deprecated || !!command.experimental; - } - const { children } = OpaqueCommandTreeNode.toInternal(node); - return children.every(child => isNodeHidden(child)); -} - type UninitializedFeature = | CliModule | CliModule[] @@ -45,6 +36,12 @@ type UninitializedFeature = interface TaggedFeature { feature: CliModule; + /** + * Whether this module was sourced from an array (e.g. cli-defaults). + * Array-sourced modules are silently skipped when any of their commands + * overlap with an individually-added module, allowing explicit module + * additions to take precedence without causing conflicts. + */ fromArray: boolean; } @@ -136,7 +133,7 @@ export class CliInitializer { const internal = OpaqueCommandTreeNode.toInternal(node); const treeParser = argParser .command(`${internal.name} [command]`, { - hidden: isNodeHidden(node), + hidden: isCommandNodeHidden(node), }) .description(internal.name); diff --git a/packages/create-app/src/lib/tasks.test.ts b/packages/create-app/src/lib/tasks.test.ts index ff2f3eb4d6..6416681b27 100644 --- a/packages/create-app/src/lib/tasks.test.ts +++ b/packages/create-app/src/lib/tasks.test.ts @@ -51,17 +51,6 @@ jest.mock('./versions', () => ({ root: '1.2.3', '@backstage/cli': '1.0.0', '@backstage/cli-defaults': '1.0.0', - '@backstage/cli-module-auth': '1.0.0', - '@backstage/cli-module-build': '1.0.0', - '@backstage/cli-module-config': '1.0.0', - '@backstage/cli-module-create-github-app': '1.0.0', - '@backstage/cli-module-info': '1.0.0', - '@backstage/cli-module-lint': '1.0.0', - '@backstage/cli-module-maintenance': '1.0.0', - '@backstage/cli-module-migrate': '1.0.0', - '@backstage/cli-module-new': '1.0.0', - '@backstage/cli-module-test-jest': '1.0.0', - '@backstage/cli-module-translations': '1.0.0', '@backstage/backend-defaults': '1.0.0', '@backstage/backend-tasks': '1.0.0', '@backstage/catalog-model': '1.0.0', diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index e770b88f3f..006dd6d7b8 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -39,17 +39,6 @@ import { version as catalogClient } from '../../../catalog-client/package.json'; import { version as catalogModel } from '../../../catalog-model/package.json'; import { version as cli } from '../../../cli/package.json'; import { version as cliDefaults } from '../../../cli-defaults/package.json'; -import { version as cliModuleAuth } from '../../../cli-module-auth/package.json'; -import { version as cliModuleBuild } from '../../../cli-module-build/package.json'; -import { version as cliModuleConfig } from '../../../cli-module-config/package.json'; -import { version as cliModuleCreateGithubApp } from '../../../cli-module-create-github-app/package.json'; -import { version as cliModuleInfo } from '../../../cli-module-info/package.json'; -import { version as cliModuleLint } from '../../../cli-module-lint/package.json'; -import { version as cliModuleMaintenance } from '../../../cli-module-maintenance/package.json'; -import { version as cliModuleMigrate } from '../../../cli-module-migrate/package.json'; -import { version as cliModuleNew } from '../../../cli-module-new/package.json'; -import { version as cliModuleTestJest } from '../../../cli-module-test-jest/package.json'; -import { version as cliModuleTranslations } from '../../../cli-module-translations/package.json'; import { version as config } from '../../../config/package.json'; import { version as coreAppApi } from '../../../core-app-api/package.json'; import { version as coreCompatApi } from '../../../core-compat-api/package.json'; @@ -120,17 +109,6 @@ export const packageVersions = { '@backstage/catalog-model': catalogModel, '@backstage/cli': cli, '@backstage/cli-defaults': cliDefaults, - '@backstage/cli-module-auth': cliModuleAuth, - '@backstage/cli-module-build': cliModuleBuild, - '@backstage/cli-module-config': cliModuleConfig, - '@backstage/cli-module-create-github-app': cliModuleCreateGithubApp, - '@backstage/cli-module-info': cliModuleInfo, - '@backstage/cli-module-lint': cliModuleLint, - '@backstage/cli-module-maintenance': cliModuleMaintenance, - '@backstage/cli-module-migrate': cliModuleMigrate, - '@backstage/cli-module-new': cliModuleNew, - '@backstage/cli-module-test-jest': cliModuleTestJest, - '@backstage/cli-module-translations': cliModuleTranslations, '@backstage/config': config, '@backstage/core-app-api': coreAppApi, '@backstage/core-compat-api': coreCompatApi, diff --git a/packages/create-app/templates/next-app/package.json.hbs b/packages/create-app/templates/next-app/package.json.hbs index 110ebc160c..49436f5fcf 100644 --- a/packages/create-app/templates/next-app/package.json.hbs +++ b/packages/create-app/templates/next-app/package.json.hbs @@ -50,17 +50,7 @@ ], "devDependencies": { "@backstage/cli": "^{{version '@backstage/cli'}}", - "@backstage/cli-module-auth": "^{{version '@backstage/cli-module-auth'}}", - "@backstage/cli-module-build": "^{{version '@backstage/cli-module-build'}}", - "@backstage/cli-module-config": "^{{version '@backstage/cli-module-config'}}", - "@backstage/cli-module-create-github-app": "^{{version '@backstage/cli-module-create-github-app'}}", - "@backstage/cli-module-info": "^{{version '@backstage/cli-module-info'}}", - "@backstage/cli-module-lint": "^{{version '@backstage/cli-module-lint'}}", - "@backstage/cli-module-maintenance": "^{{version '@backstage/cli-module-maintenance'}}", - "@backstage/cli-module-migrate": "^{{version '@backstage/cli-module-migrate'}}", - "@backstage/cli-module-new": "^{{version '@backstage/cli-module-new'}}", - "@backstage/cli-module-test-jest": "^{{version '@backstage/cli-module-test-jest'}}", - "@backstage/cli-module-translations": "^{{version '@backstage/cli-module-translations'}}", + "@backstage/cli-defaults": "^{{version '@backstage/cli-defaults'}}", "@backstage/e2e-test-utils": "^{{version '@backstage/e2e-test-utils'}}", "@jest/environment-jsdom-abstract": "^30.0.0", "@playwright/test": "^1.32.3", diff --git a/packages/repo-tools/src/commands/api-reports/cli-reports/runCliExtraction.ts b/packages/repo-tools/src/commands/api-reports/cli-reports/runCliExtraction.ts index 7dfbba51ec..ce207489a7 100644 --- a/packages/repo-tools/src/commands/api-reports/cli-reports/runCliExtraction.ts +++ b/packages/repo-tools/src/commands/api-reports/cli-reports/runCliExtraction.ts @@ -132,6 +132,11 @@ export async function runCliExtraction({ const pkgJson = await fs.readJson(resolvePath(fullDir, 'package.json')); if (!pkgJson.bin) { + if (pkgJson.backstage?.role === 'cli') { + throw new Error( + `CLI package ${pkgJson.name} is missing a "bin" field in its package.json`, + ); + } continue; } diff --git a/yarn.lock b/yarn.lock index 1c4ba53f5e..ff47745d26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2801,7 +2801,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-defaults@workspace:^, @backstage/cli-defaults@workspace:packages/cli-defaults": +"@backstage/cli-defaults@workspace:*, @backstage/cli-defaults@workspace:^, @backstage/cli-defaults@workspace:packages/cli-defaults": version: 0.0.0-use.local resolution: "@backstage/cli-defaults@workspace:packages/cli-defaults" dependencies: @@ -2809,7 +2809,7 @@ __metadata: "@backstage/cli-module-auth": "workspace:^" "@backstage/cli-module-build": "workspace:^" "@backstage/cli-module-config": "workspace:^" - "@backstage/cli-module-create-github-app": "workspace:^" + "@backstage/cli-module-github": "workspace:^" "@backstage/cli-module-info": "workspace:^" "@backstage/cli-module-lint": "workspace:^" "@backstage/cli-module-maintenance": "workspace:^" @@ -2820,7 +2820,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-auth@workspace:*, @backstage/cli-module-auth@workspace:^, @backstage/cli-module-auth@workspace:packages/cli-module-auth": +"@backstage/cli-module-auth@workspace:^, @backstage/cli-module-auth@workspace:packages/cli-module-auth": version: 0.0.0-use.local resolution: "@backstage/cli-module-auth@workspace:packages/cli-module-auth" dependencies: @@ -2847,7 +2847,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-build@workspace:*, @backstage/cli-module-build@workspace:^, @backstage/cli-module-build@workspace:packages/cli-module-build": +"@backstage/cli-module-build@workspace:^, @backstage/cli-module-build@workspace:packages/cli-module-build": version: 0.0.0-use.local resolution: "@backstage/cli-module-build@workspace:packages/cli-module-build" dependencies: @@ -2894,7 +2894,6 @@ __metadata: node-stdlib-browser: "npm:^1.3.1" npm-packlist: "npm:^5.0.0" p-queue: "npm:^6.6.2" - pirates: "npm:^4.0.6" postcss: "npm:^8.1.0" postcss-import: "npm:^16.1.0" process: "npm:^0.11.10" @@ -2922,7 +2921,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-config@workspace:*, @backstage/cli-module-config@workspace:^, @backstage/cli-module-config@workspace:packages/cli-module-config": +"@backstage/cli-module-config@workspace:^, @backstage/cli-module-config@workspace:packages/cli-module-config": version: 0.0.0-use.local resolution: "@backstage/cli-module-config@workspace:packages/cli-module-config" dependencies: @@ -2944,9 +2943,9 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-create-github-app@workspace:*, @backstage/cli-module-create-github-app@workspace:^, @backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app": +"@backstage/cli-module-github@workspace:^, @backstage/cli-module-github@workspace:packages/cli-module-github": version: 0.0.0-use.local - resolution: "@backstage/cli-module-create-github-app@workspace:packages/cli-module-create-github-app" + resolution: "@backstage/cli-module-github@workspace:packages/cli-module-github" dependencies: "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" @@ -2962,11 +2961,11 @@ __metadata: react-dev-utils: "npm:^12.0.0-next.60" yaml: "npm:^2.0.0" bin: - cli-module-create-github-app: bin/backstage-cli-module-create-github-app + cli-module-github: bin/backstage-cli-module-github languageName: unknown linkType: soft -"@backstage/cli-module-info@workspace:*, @backstage/cli-module-info@workspace:^, @backstage/cli-module-info@workspace:packages/cli-module-info": +"@backstage/cli-module-info@workspace:^, @backstage/cli-module-info@workspace:packages/cli-module-info": version: 0.0.0-use.local resolution: "@backstage/cli-module-info@workspace:packages/cli-module-info" dependencies: @@ -2982,7 +2981,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-lint@workspace:*, @backstage/cli-module-lint@workspace:^, @backstage/cli-module-lint@workspace:packages/cli-module-lint": +"@backstage/cli-module-lint@workspace:^, @backstage/cli-module-lint@workspace:packages/cli-module-lint": version: 0.0.0-use.local resolution: "@backstage/cli-module-lint@workspace:packages/cli-module-lint" dependencies: @@ -3003,7 +3002,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-maintenance@workspace:*, @backstage/cli-module-maintenance@workspace:^, @backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance": +"@backstage/cli-module-maintenance@workspace:^, @backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance": version: 0.0.0-use.local resolution: "@backstage/cli-module-maintenance@workspace:packages/cli-module-maintenance" dependencies: @@ -3020,7 +3019,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-migrate@workspace:*, @backstage/cli-module-migrate@workspace:^, @backstage/cli-module-migrate@workspace:packages/cli-module-migrate": +"@backstage/cli-module-migrate@workspace:^, @backstage/cli-module-migrate@workspace:packages/cli-module-migrate": version: 0.0.0-use.local resolution: "@backstage/cli-module-migrate@workspace:packages/cli-module-migrate" dependencies: @@ -3047,7 +3046,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-new@workspace:*, @backstage/cli-module-new@workspace:^, @backstage/cli-module-new@workspace:packages/cli-module-new": +"@backstage/cli-module-new@workspace:^, @backstage/cli-module-new@workspace:packages/cli-module-new": version: 0.0.0-use.local resolution: "@backstage/cli-module-new@workspace:packages/cli-module-new" dependencies: @@ -3079,7 +3078,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-test-jest@workspace:*, @backstage/cli-module-test-jest@workspace:^, @backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest": +"@backstage/cli-module-test-jest@workspace:^, @backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest": version: 0.0.0-use.local resolution: "@backstage/cli-module-test-jest@workspace:packages/cli-module-test-jest" dependencies: @@ -3112,7 +3111,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-module-translations@workspace:*, @backstage/cli-module-translations@workspace:^, @backstage/cli-module-translations@workspace:packages/cli-module-translations": +"@backstage/cli-module-translations@workspace:^, @backstage/cli-module-translations@workspace:packages/cli-module-translations": version: 0.0.0-use.local resolution: "@backstage/cli-module-translations@workspace:packages/cli-module-translations" dependencies: @@ -3139,12 +3138,14 @@ __metadata: "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@manypkg/get-packages": "npm:^1.1.3" + "@swc/core": "npm:^1.15.6" "@types/yarnpkg__lockfile": "npm:^1.1.4" "@yarnpkg/lockfile": "npm:^1.1.0" "@yarnpkg/parsers": "npm:^3.0.0" chalk: "npm:^4.0.0" commander: "npm:^12.0.0" fs-extra: "npm:^11.2.0" + pirates: "npm:^4.0.6" semver: "npm:^7.5.3" yaml: "npm:^2.0.0" zod: "npm:^3.25.76" @@ -45365,17 +45366,7 @@ __metadata: resolution: "root@workspace:." dependencies: "@backstage/cli": "workspace:*" - "@backstage/cli-module-auth": "workspace:*" - "@backstage/cli-module-build": "workspace:*" - "@backstage/cli-module-config": "workspace:*" - "@backstage/cli-module-create-github-app": "workspace:*" - "@backstage/cli-module-info": "workspace:*" - "@backstage/cli-module-lint": "workspace:*" - "@backstage/cli-module-maintenance": "workspace:*" - "@backstage/cli-module-migrate": "workspace:*" - "@backstage/cli-module-new": "workspace:*" - "@backstage/cli-module-test-jest": "workspace:*" - "@backstage/cli-module-translations": "workspace:*" + "@backstage/cli-defaults": "workspace:*" "@backstage/codemods": "workspace:*" "@backstage/create-app": "workspace:*" "@backstage/e2e-test-utils": "workspace:*" From 92b0f79d9ce65e9f2c8024dbefc71bcaffbf8b9b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 13:03:17 +0100 Subject: [PATCH 43/45] Make @swc/core an optional peer dependency of cli-node The node transform config is only loaded at runtime when running backend processes, so @swc/core should not be a hard dependency for all cli-node consumers. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- packages/cli-node/package.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/cli-node/package.json b/packages/cli-node/package.json index e266088176..483b0eccff 100644 --- a/packages/cli-node/package.json +++ b/packages/cli-node/package.json @@ -36,7 +36,6 @@ "@backstage/errors": "workspace:^", "@backstage/types": "workspace:^", "@manypkg/get-packages": "^1.1.3", - "@swc/core": "^1.15.6", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "^3.0.0", "chalk": "^4.0.0", @@ -52,5 +51,13 @@ "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@types/yarnpkg__lockfile": "^1.1.4" + }, + "peerDependencies": { + "@swc/core": "^1.15.6" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + } } } From ede7195275e64dad8cfc6f8eeab63645b5f6a588 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 13:08:09 +0100 Subject: [PATCH 44/45] chore: update yarn.lock for cli-node peer dependency changes Signed-off-by: Patrik Oldsberg Made-with: Cursor --- yarn.lock | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index ff47745d26..90ac7fa1c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3138,7 +3138,6 @@ __metadata: "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@manypkg/get-packages": "npm:^1.1.3" - "@swc/core": "npm:^1.15.6" "@types/yarnpkg__lockfile": "npm:^1.1.4" "@yarnpkg/lockfile": "npm:^1.1.0" "@yarnpkg/parsers": "npm:^3.0.0" @@ -3149,6 +3148,11 @@ __metadata: semver: "npm:^7.5.3" yaml: "npm:^2.0.0" zod: "npm:^3.25.76" + peerDependencies: + "@swc/core": ^1.15.6 + peerDependenciesMeta: + "@swc/core": + optional: true languageName: unknown linkType: soft From 08dbd83cd3c1443c55792748c6dfa4bf12ca1872 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Mar 2026 13:12:00 +0100 Subject: [PATCH 45/45] chore: remove redundant cli.ts files from CLI modules The bin scripts already had the full runCliModule logic for the production path. Inline the same pattern for local dev and drop the intermediate src/cli.ts files that just duplicated it. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../bin/backstage-cli-module-auth | 13 +++++----- packages/cli-module-auth/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-build | 13 +++++----- packages/cli-module-build/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-config | 13 +++++----- packages/cli-module-config/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-github | 13 +++++----- packages/cli-module-github/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-info | 13 +++++----- packages/cli-module-info/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-lint | 13 +++++----- packages/cli-module-lint/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-maintenance | 13 +++++----- packages/cli-module-maintenance/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-migrate | 13 +++++----- packages/cli-module-migrate/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-new | 13 +++++----- packages/cli-module-new/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-test-jest | 13 +++++----- packages/cli-module-test-jest/src/cli.ts | 26 ------------------- .../bin/backstage-cli-module-translations | 13 +++++----- packages/cli-module-translations/src/cli.ts | 26 ------------------- 22 files changed, 66 insertions(+), 363 deletions(-) delete mode 100644 packages/cli-module-auth/src/cli.ts delete mode 100644 packages/cli-module-build/src/cli.ts delete mode 100644 packages/cli-module-config/src/cli.ts delete mode 100644 packages/cli-module-github/src/cli.ts delete mode 100644 packages/cli-module-info/src/cli.ts delete mode 100644 packages/cli-module-lint/src/cli.ts delete mode 100644 packages/cli-module-maintenance/src/cli.ts delete mode 100644 packages/cli-module-migrate/src/cli.ts delete mode 100644 packages/cli-module-new/src/cli.ts delete mode 100644 packages/cli-module-test-jest/src/cli.ts delete mode 100644 packages/cli-module-translations/src/cli.ts diff --git a/packages/cli-module-auth/bin/backstage-cli-module-auth b/packages/cli-module-auth/bin/backstage-cli-module-auth index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-auth/bin/backstage-cli-module-auth +++ b/packages/cli-module-auth/bin/backstage-cli-module-auth @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-auth/src/cli.ts b/packages/cli-module-auth/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-auth/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-build/bin/backstage-cli-module-build b/packages/cli-module-build/bin/backstage-cli-module-build index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-build/bin/backstage-cli-module-build +++ b/packages/cli-module-build/bin/backstage-cli-module-build @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-build/src/cli.ts b/packages/cli-module-build/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-build/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-config/bin/backstage-cli-module-config b/packages/cli-module-config/bin/backstage-cli-module-config index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-config/bin/backstage-cli-module-config +++ b/packages/cli-module-config/bin/backstage-cli-module-config @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-config/src/cli.ts b/packages/cli-module-config/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-config/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-github/bin/backstage-cli-module-github b/packages/cli-module-github/bin/backstage-cli-module-github index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-github/bin/backstage-cli-module-github +++ b/packages/cli-module-github/bin/backstage-cli-module-github @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-github/src/cli.ts b/packages/cli-module-github/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-github/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-info/bin/backstage-cli-module-info b/packages/cli-module-info/bin/backstage-cli-module-info index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-info/bin/backstage-cli-module-info +++ b/packages/cli-module-info/bin/backstage-cli-module-info @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-info/src/cli.ts b/packages/cli-module-info/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-info/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-lint/bin/backstage-cli-module-lint b/packages/cli-module-lint/bin/backstage-cli-module-lint index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-lint/bin/backstage-cli-module-lint +++ b/packages/cli-module-lint/bin/backstage-cli-module-lint @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-lint/src/cli.ts b/packages/cli-module-lint/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-lint/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-maintenance/bin/backstage-cli-module-maintenance b/packages/cli-module-maintenance/bin/backstage-cli-module-maintenance index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-maintenance/bin/backstage-cli-module-maintenance +++ b/packages/cli-module-maintenance/bin/backstage-cli-module-maintenance @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-maintenance/src/cli.ts b/packages/cli-module-maintenance/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-maintenance/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-migrate/bin/backstage-cli-module-migrate b/packages/cli-module-migrate/bin/backstage-cli-module-migrate index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-migrate/bin/backstage-cli-module-migrate +++ b/packages/cli-module-migrate/bin/backstage-cli-module-migrate @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-migrate/src/cli.ts b/packages/cli-module-migrate/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-migrate/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-new/bin/backstage-cli-module-new b/packages/cli-module-new/bin/backstage-cli-module-new index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-new/bin/backstage-cli-module-new +++ b/packages/cli-module-new/bin/backstage-cli-module-new @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-new/src/cli.ts b/packages/cli-module-new/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-new/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-test-jest/bin/backstage-cli-module-test-jest b/packages/cli-module-test-jest/bin/backstage-cli-module-test-jest index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-test-jest/bin/backstage-cli-module-test-jest +++ b/packages/cli-module-test-jest/bin/backstage-cli-module-test-jest @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-test-jest/src/cli.ts b/packages/cli-module-test-jest/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-test-jest/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -}); diff --git a/packages/cli-module-translations/bin/backstage-cli-module-translations b/packages/cli-module-translations/bin/backstage-cli-module-translations index 885c06db9f..68bdc76a4a 100755 --- a/packages/cli-module-translations/bin/backstage-cli-module-translations +++ b/packages/cli-module-translations/bin/backstage-cli-module-translations @@ -22,12 +22,11 @@ const isLocal = require('node:fs').existsSync( path.resolve(__dirname, '../src'), ); -if (!isLocal) { - const { runCliModule } = require('@backstage/cli-node'); - const cliModule = require('..').default; - const pkg = require('../package.json'); - runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); -} else { +if (isLocal) { require('@backstage/cli-node/config/nodeTransform.cjs'); - require('../src/cli'); } + +const { runCliModule } = require('@backstage/cli-node'); +const cliModule = require(isLocal ? '../src/index' : '..').default; +const pkg = require('../package.json'); +runCliModule({ module: cliModule, name: pkg.name, version: pkg.version }); diff --git a/packages/cli-module-translations/src/cli.ts b/packages/cli-module-translations/src/cli.ts deleted file mode 100644 index 6d4b925cf1..0000000000 --- a/packages/cli-module-translations/src/cli.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { runCliModule } from '@backstage/cli-node'; -import cliModule from './index'; - -const pkg = require('../package.json') as { name: string; version: string }; - -runCliModule({ - module: cliModule, - name: pkg.name, - version: pkg.version, -});