cli/commands/new: restore ability to pre-fill options and set globals via args

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2025-02-06 23:42:05 +01:00
parent e6535e0f26
commit e0833d2fd8
3 changed files with 68 additions and 12 deletions
+20
View File
@@ -251,6 +251,26 @@ export function registerCommands(program: Command) {
'--select <name>',
'Select the thing you want to be creating upfront',
)
.option(
'--option <name>=<value>',
'Pre-fill options for the creation process',
(opt, arr: string[]) => [...arr, opt],
[],
)
.option('--scope <scope>', 'The scope to use for new packages')
.option(
'--npm-registry <URL>',
'The package registry to use for new packages',
)
.option(
'--baseVersion <version>',
'The version to use for any new packages (default: 0.1.0)',
)
.option(
'--license <license>',
'The license to use for any new packages (default: Apache-2.0)',
)
.option('--no-private', 'Do not mark new packages as private')
.action(lazy(() => import('./new/new'), 'default'));
registerConfigCommands(program);
+36 -3
View File
@@ -43,6 +43,23 @@ import { executePluginPackageTemplate } from '../../lib/new/executeTemplate';
import { TemporaryDirectoryManager } from './TemporaryDirectoryManager';
import { OptionValues } from 'commander';
function parseOptions(optionStrings: string[]): Record<string, string> {
const options: Record<string, string> = {};
for (const str of optionStrings) {
const [key] = str.split('=', 1);
const value = str.slice(key.length + 1);
if (!key || str[key.length] !== '=') {
throw new Error(
`Invalid option '${str}', must be of the format <key>=<value>`,
);
}
options[key] = value;
}
return options;
}
export default async (opts: OptionValues) => {
const pkgJson = await fs.readJson(paths.resolveTargetRoot('package.json'));
const cliConfig = pkgJson.backstage?.cli;
@@ -54,12 +71,28 @@ export default async (opts: OptionValues) => {
const codeOwnersFilePath = await getCodeownersFilePath(paths.targetRoot);
const prompts = await promptOptions({
prompts: template.prompts || [],
const legacyOpts = parseOptions(opts.option);
const prefilledAnswers = Object.fromEntries(
(template.prompts ?? []).flatMap(prompt => {
const id = typeof prompt === 'string' ? prompt : prompt.id;
const answer = legacyOpts[id];
return answer ? [[id, answer]] : [];
}),
);
const promptAnswers = await promptOptions({
prompts:
template.prompts?.filter(
prompt =>
!Object.hasOwn(
prefilledAnswers,
typeof prompt === 'string' ? prompt : prompt.id,
),
) ?? [],
globals,
codeOwnersFilePath,
});
const options = populateOptions(prompts, template);
const answers = { ...prefilledAnswers, ...promptAnswers };
const options = populateOptions(answers, template, opts);
const tmpDirManager = TemporaryDirectoryManager.create();
+12 -9
View File
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { OptionValues } from 'commander';
import { Template } from './types';
export interface Options extends Record<string, string | boolean> {
@@ -50,19 +51,21 @@ export const resolvePackageName = (options: {
};
export function populateOptions(
prompts: Record<string, string>,
options: Record<string, string>,
template: Template,
argOpts?: OptionValues,
): Options {
return {
id: prompts.id ?? '',
private: !!prompts.private,
baseVersion: prompts.baseVersion ?? '0.1.0',
owner: prompts.owner ?? '',
license: prompts.license ?? 'Apache-2.0',
id: '',
owner: '',
license: 'Apache-2.0',
scope: '',
moduleId: '',
baseVersion: '0.1.0',
private: true,
...options,
...argOpts,
targetPath: template.targetPath,
scope: prompts.scope ?? '',
moduleId: prompts.moduleId ?? '',
...prompts,
};
}