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 <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-03-16 12:55:22 +01:00
parent 26eab3bf83
commit 4d081452b1
47 changed files with 147 additions and 185 deletions
+2 -2
View File
@@ -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.',
);
}
+1 -1
View File
@@ -17,4 +17,4 @@
export {
resolve,
load,
} from '@backstage/cli-module-build/config/nodeTransformHooks.mjs';
} from '@backstage/cli-node/config/nodeTransformHooks.mjs';
+8 -11
View File
@@ -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);