cli: refactor create factories to use common prompts

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-11-12 16:08:32 +01:00
parent 1c0ac6291c
commit 142cd41b7e
4 changed files with 70 additions and 72 deletions
@@ -28,6 +28,7 @@ import { createFactory, CreateContext } from '../types';
import { Lockfile } from '../../versioning';
import { addPackageDependency, Task, templatingTask } from '../../tasks';
import { createPackageVersionProvider } from '../../version';
import { ownerPrompt, pluginIdPrompt } from './common/prompts';
type Options = {
id: string;
@@ -41,39 +42,7 @@ export const backendPlugin = createFactory<Options>({
optionsDiscovery: async () => ({
codeOwnersPath: await getCodeownersFilePath(paths.targetRoot),
}),
optionsPrompts: [
{
type: 'input',
name: 'id',
message: 'Enter an ID for the plugin [required]',
validate: (value: string) => {
if (!value) {
return 'Please enter an ID for the plugin';
} else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {
return 'Plugin IDs must be lowercase and contain only letters, digits, and dashes.';
}
return true;
},
},
{
type: 'input',
name: 'owner',
message: 'Enter an owner of the plugin to add to CODEOWNERS [optional]',
when: opts => Boolean(opts.codeOwnersPath),
validate: (value: string) => {
if (!value) {
return true;
}
const ownerIds = parseOwnerIds(value);
if (!ownerIds) {
return 'The owner must be a space separated list of team names (e.g. @org/team-name), usernames (e.g. @username), or the email addresses (e.g. user@example.com).';
}
return true;
},
},
],
optionsPrompts: [pluginIdPrompt(), ownerPrompt()],
async create(options: Options, ctx: CreateContext) {
const id = `${options.id}-backend`;
const name = ctx.scope ? `@${ctx.scope}/plugin-${id}` : `plugin-${id}`;
@@ -0,0 +1,58 @@
/*
* 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.
*/
import { Prompt } from '../../types';
import { parseOwnerIds } from '../../../codeowners';
export function pluginIdPrompt(): Prompt<{ id: string }> {
return {
type: 'input',
name: 'id',
message: 'Enter the ID of the plugin [required]',
validate: (value: string) => {
if (!value) {
return 'Please enter the ID of the plugin';
} else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {
return 'Plugin IDs must be lowercase and contain only letters, digits, and dashes.';
}
return true;
},
};
}
export function ownerPrompt(): Prompt<{
owner?: string;
codeOwnersPath?: string;
}> {
return {
type: 'input',
name: 'owner',
message: 'Enter an owner to add to CODEOWNERS [optional]',
when: opts => Boolean(opts.codeOwnersPath),
validate: (value: string) => {
if (!value) {
return true;
}
const ownerIds = parseOwnerIds(value);
if (!ownerIds) {
return 'The owner must be a space separated list of team names (e.g. @org/team-name), usernames (e.g. @username), or the email addresses (e.g. user@example.com).';
}
return true;
},
};
}
@@ -28,6 +28,7 @@ import { createFactory, CreateContext } from '../types';
import { Lockfile } from '../../versioning';
import { addPackageDependency, Task, templatingTask } from '../../tasks';
import { createPackageVersionProvider } from '../../version';
import { ownerPrompt, pluginIdPrompt } from './common/prompts';
type Options = {
id: string;
@@ -41,39 +42,7 @@ export const frontendPlugin = createFactory<Options>({
optionsDiscovery: async () => ({
codeOwnersPath: await getCodeownersFilePath(paths.targetRoot),
}),
optionsPrompts: [
{
type: 'input',
name: 'id',
message: 'Enter an ID for the plugin [required]',
validate: (value: string) => {
if (!value) {
return 'Please enter an ID for the plugin';
} else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {
return 'Plugin IDs must be lowercase and contain only letters, digits, and dashes.';
}
return true;
},
},
{
type: 'input',
name: 'owner',
message: 'Enter an owner of the plugin to add to CODEOWNERS [optional]',
when: opts => Boolean(opts.codeOwnersPath),
validate: (value: string) => {
if (!value) {
return true;
}
const ownerIds = parseOwnerIds(value);
if (!ownerIds) {
return 'The owner must be a space separated list of team names (e.g. @org/team-name), usernames (e.g. @username), or the email addresses (e.g. user@example.com).';
}
return true;
},
},
],
optionsPrompts: [pluginIdPrompt(), ownerPrompt()],
async create(options: Options, ctx: CreateContext) {
const { id } = options;
+8 -6
View File
@@ -37,18 +37,20 @@ export interface CreateContext {
export type AnyOptions = Record<string, string>;
export interface Factory<Options extends AnyOptions> {
export type Prompt<TOptions> = DistinctQuestion<TOptions> & { name: string };
export interface Factory<TOptions extends AnyOptions> {
name: string;
description: string;
optionsDiscovery?(): Promise<Partial<Options>>;
optionsPrompts?: ReadonlyArray<DistinctQuestion<Options> & { name: string }>;
create(options: Options, context?: CreateContext): Promise<void>;
optionsDiscovery?(): Promise<Partial<TOptions>>;
optionsPrompts?: ReadonlyArray<Prompt<TOptions>>;
create(options: TOptions, context?: CreateContext): Promise<void>;
}
export type AnyFactory = Factory<AnyOptions>;
export function createFactory<Options extends AnyOptions>(
config: Factory<Options>,
export function createFactory<TOptions extends AnyOptions>(
config: Factory<TOptions>,
): AnyFactory {
return config as AnyFactory;
}