Skip to content

Commit

Permalink
[cli] refactor confirm component to use client.input.confirm interf…
Browse files Browse the repository at this point in the history
…ace (vercel#12846)

Moves the restrictive interface for the `confirm` function to
`client.input.confirm`, and refactors all call sites to use the updated
interface. This PR removes any confusion about whether to use the
`input.confirm` method or the `confirm` function.

Previous discussion:
vercel#12834 (comment)
  • Loading branch information
erikareads authored Jan 13, 2025
1 parent 2ed7b82 commit 2378fd6
Show file tree
Hide file tree
Showing 30 changed files with 59 additions and 113 deletions.
5 changes: 5 additions & 0 deletions .changeset/perfect-guests-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vercel": patch
---

[cli] refactor confirm component to use `client.input.confirm` interface
3 changes: 1 addition & 2 deletions packages/cli/src/commands/alias/rm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type Client from '../../util/client';
import getScope from '../../util/get-scope';
import removeAliasById from '../../util/alias/remove-alias-by-id';
import stamp from '../../util/output/stamp';
import confirm from '../../util/input/confirm';
import findAliasByAliasOrId from '../../util/alias/find-alias-by-alias-or-id';
import { isValidName } from '../../util/is-valid-name';
import { getCommandName } from '../../util/pkg-name';
Expand Down Expand Up @@ -100,5 +99,5 @@ async function confirmAliasRemove(client: Client, alias: Alias) {

output.log('The following alias will be removed permanently');
output.print(` ${tbl}\n`);
return confirm(client, chalk.red('Are you sure?'), false);
return client.input.confirm(chalk.red('Are you sure?'), false);
}
4 changes: 1 addition & 3 deletions packages/cli/src/commands/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ import { CantParseJSONFile } from '../../util/errors-ts';
import { parseArguments } from '../../util/get-args';
import { staticFiles as getFiles } from '../../util/get-files';
import { getFlagsSpecification } from '../../util/get-flags-specification';
import confirm from '../../util/input/confirm';
import cmd from '../../util/output/cmd';
import stamp from '../../util/output/stamp';
import parseTarget from '../../util/parse-target';
Expand Down Expand Up @@ -206,8 +205,7 @@ export default async function main(client: Client): Promise<number> {
return 1;
}

confirmed = await confirm(
client,
confirmed = await client.input.confirm(
`No Project Settings found locally. Run ${cli.getCommandName(
'pull'
)} for retrieving them?`,
Expand Down
7 changes: 2 additions & 5 deletions packages/cli/src/commands/domains/buy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import getDomainPrice from '../../util/domains/get-domain-price';
import getDomainStatus from '../../util/domains/get-domain-status';
import getScope from '../../util/get-scope';
import param from '../../util/output/param';
import confirm from '../../util/input/confirm';
import purchaseDomain from '../../util/domains/purchase-domain';
import stamp from '../../util/output/stamp';
import { getCommandName } from '../../util/pkg-name';
Expand Down Expand Up @@ -97,8 +96,7 @@ export default async function buy(client: Client, argv: string[]) {
autoRenew = true;
} else {
if (
!(await confirm(
client,
!(await client.input.confirm(
`Buy now for ${chalk.bold(`$${price}`)} (${`${period}yr${
period > 1 ? 's' : ''
}`})?`,
Expand All @@ -108,8 +106,7 @@ export default async function buy(client: Client, argv: string[]) {
return 0;
}

autoRenew = await confirm(
client,
autoRenew = await client.input.confirm(
renewalPrice.period === 1
? `Auto renew yearly for ${chalk.bold(`$${price}`)}?`
: `Auto renew every ${renewalPrice.period} years for ${chalk.bold(
Expand Down
7 changes: 2 additions & 5 deletions packages/cli/src/commands/domains/move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import isRootDomain from '../../util/is-root-domain';
import param from '../../util/output/param';
import getDomainAliases from '../../util/alias/get-domain-aliases';
import getDomainByName from '../../util/domains/get-domain-by-name';
import confirm from '../../util/input/confirm';
import getTeams from '../../util/teams/get-teams';
import { getCommandName } from '../../util/pkg-name';
import output from '../../output-manager';
Expand Down Expand Up @@ -82,8 +81,7 @@ export default async function move(client: Client, argv: string[]) {
)} will have 24 hours to accept your move request before it expires.`
);
if (
!(await confirm(
client,
!(await client.input.confirm(
`Are you sure you want to move ${param(domainName)} to ${param(
destination
)}?`,
Expand All @@ -104,8 +102,7 @@ export default async function move(client: Client, argv: string[]) {
)} will be removed. Run ${getCommandName(`alias ls`)} to list them.`
);
if (
!(await confirm(
client,
!(await client.input.confirm(
`Are you sure you want to move ${param(domainName)}?`,
false
))
Expand Down
7 changes: 2 additions & 5 deletions packages/cli/src/commands/domains/rm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import removeDomainByName from '../../util/domains/remove-domain-by-name';
import stamp from '../../util/output/stamp';
import * as ERRORS from '../../util/errors-ts';
import param from '../../util/output/param';
import confirm from '../../util/input/confirm';
import setCustomSuffix from '../../util/domains/set-custom-suffix';
import { findProjectsForDomain } from '../../util/projects/find-projects-for-domain';
import { getCommandName } from '../../util/pkg-name';
Expand Down Expand Up @@ -95,8 +94,7 @@ export default async function rm(client: Client, argv: string[]) {
const skipConfirmation = opts['--yes'] || false;
if (
!skipConfirmation &&
!(await confirm(
client,
!(await client.input.confirm(
`Are you sure you want to remove ${param(domainName)}?`,
false
))
Expand Down Expand Up @@ -236,8 +234,7 @@ async function removeDomain(

if (
!skipConfirmation &&
!(await confirm(
client,
!(await client.input.confirm(
`Remove conflicts associated with domain?`,
false
))
Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/commands/domains/transfer-in.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import stamp from '../../util/output/stamp';
import getAuthCode from '../../util/domains/get-auth-code';
import getDomainPrice from '../../util/domains/get-domain-price';
import checkTransfer from '../../util/domains/check-transfer';
import confirm from '../../util/input/confirm';
import isRootDomain from '../../util/is-root-domain';
import { getCommandName } from '../../util/pkg-name';
import { DomainsTransferInTelemetryClient } from '../../util/telemetry/commands/domains/transfer-in';
Expand Down Expand Up @@ -84,8 +83,7 @@ export default async function transferIn(client: Client, argv: string[]) {

const authCode = await getAuthCode(client, opts['--code']);

const shouldTransfer = await confirm(
client,
const shouldTransfer = await client.input.confirm(
transferPolicy === 'no-change'
? `Transfer now for ${chalk.bold(`$${price}`)}?`
: `Transfer now with 1yr renewal for ${chalk.bold(`$${price}`)}?`,
Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/commands/env/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { closeSync, openSync, readSync } from 'fs';
import { resolve } from 'path';
import type Client from '../../util/client';
import { emoji, prependEmoji } from '../../util/emoji';
import confirm from '../../util/input/confirm';
import param from '../../util/output/param';
import stamp from '../../util/output/stamp';
import { getCommandName } from '../../util/pkg-name';
Expand Down Expand Up @@ -148,8 +147,7 @@ export async function envPullCommandLogic(
} else if (
exists &&
!skipConfirmation &&
!(await confirm(
client,
!(await client.input.confirm(
`Found existing file ${param(filename)}. Do you want to overwrite?`,
false
))
Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/commands/env/rm.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import chalk from 'chalk';
import confirm from '../../util/input/confirm';
import removeEnvRecord from '../../util/env/remove-env-record';
import getEnvRecords from '../../util/env/get-env-records';
import formatEnvironments from '../../util/env/format-environments';
Expand Down Expand Up @@ -109,8 +108,7 @@ export default async function rm(client: Client, argv: string[]) {
const skipConfirmation = opts['--yes'];
if (
!skipConfirmation &&
!(await confirm(
client,
!(await client.input.confirm(
`Removing Environment Variable ${param(env.key)} from ${formatEnvironments(
link,
env,
Expand Down
7 changes: 2 additions & 5 deletions packages/cli/src/commands/git/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { join } from 'path';
import type { Org, Project, ProjectLinkData } from '@vercel-internals/types';
import type Client from '../../util/client';
import { parseGitConfig, pluckRemoteUrls } from '../../util/create-git-meta';
import confirm from '../../util/input/confirm';
import list, { type ListChoice } from '../../util/input/list';
import link from '../../util/output/link';
import { getCommandName } from '../../util/pkg-name';
Expand Down Expand Up @@ -327,8 +326,7 @@ async function promptConnectArg({
let shouldConnect = yes;
if (!shouldConnect) {
const { url: repoUrlFromArg } = repoInfoFromArg;
shouldConnect = await confirm(
client,
shouldConnect = await client.input.confirm(
`Do you still want to connect ${link(repoUrlFromArg)}?`,
false
);
Expand Down Expand Up @@ -408,8 +406,7 @@ async function confirmRepoConnect(
) {
let shouldReplaceProject = yes;
if (!shouldReplaceProject) {
shouldReplaceProject = await confirm(
client,
shouldReplaceProject = await client.input.confirm(
`Looks like you already have a ${formatProvider(
connectedProvider
)} repository connected: ${chalk.cyan(
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/git/disconnect.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import chalk from 'chalk';
import confirm from '../../util/input/confirm';

import { getCommandName } from '../../util/pkg-name';
import { disconnectGitProvider } from '../../util/git/connect-git-provider';
import output from '../../output-manager';
Expand Down Expand Up @@ -64,8 +64,7 @@ export default async function disconnect(client: Client, argv: string[]) {
);
const confirmDisconnect =
autoConfirm ||
(await confirm(
client,
(await client.input.confirm(
`Are you sure you want to disconnect ${chalk.cyan(
`${linkOrg}/${repo}`
)} from your project?`,
Expand Down
5 changes: 3 additions & 2 deletions packages/cli/src/commands/init/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import chalk from 'chalk';
// @ts-ignore
import listInput from '../../util/input/list';
import listItem from '../../util/output/list-item';
import confirm from '../../util/input/confirm';
import toHumanPath from '../../util/humanize-path';
import type Client from '../../util/client';
import cmd from '../../util/output/cmd';
Expand Down Expand Up @@ -224,7 +223,9 @@ async function guess(client: Client, exampleList: string[], name: string) {
const found = didYouMean(name, exampleList, 0.7);

if (typeof found === 'string') {
if (await confirm(client, `Did you mean ${chalk.bold(found)}?`, false)) {
if (
await client.input.confirm(`Did you mean ${chalk.bold(found)}?`, false)
) {
return found;
}
} else {
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/commands/integration-resource/disconnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { parseArguments } from '../../util/get-args';
import { getFlagsSpecification } from '../../util/get-flags-specification';
import getScope from '../../util/get-scope';
import { printError } from '../../util/error';
import confirm from '../../util/input/confirm';
import {
disconnectResourceFromAllProjects,
disconnectResourceFromProject,
Expand Down Expand Up @@ -217,7 +216,7 @@ async function confirmDisconnectProject(
output.log(
`The resource ${chalk.bold(resource.name)} will be disconnected from project ${chalk.bold(project.name)}.`
);
return confirm(client, `${chalk.red('Are you sure?')}`, false);
return client.input.confirm(`${chalk.red('Are you sure?')}`, false);
}

async function confirmDisconnectAllProjects(
Expand All @@ -231,5 +230,5 @@ async function confirmDisconnectAllProjects(
for (const project of resource.projectsMetadata) {
output.print(` ${project.name}\n`);
}
return confirm(client, chalk.red('Are you sure?'), false);
return client.input.confirm(chalk.red('Are you sure?'), false);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { parseArguments } from '../../util/get-args';
import { getFlagsSpecification } from '../../util/get-flags-specification';
import getScope from '../../util/get-scope';
import { printError } from '../../util/error';
import confirm from '../../util/input/confirm';
import { deleteResource as _deleteResource } from '../../util/integration-resource/delete-resource';
import { getResources } from '../../util/integration-resource/get-resources';
import {
Expand Down Expand Up @@ -144,5 +143,5 @@ async function confirmDeleteResource(
resource: Resource
): Promise<boolean> {
output.log(`${chalk.bold(resource.name)} will be deleted permanently.`);
return confirm(client, `${chalk.red('Are you sure?')}`, false);
return client.input.confirm(`${chalk.red('Are you sure?')}`, false);
}
9 changes: 3 additions & 6 deletions packages/cli/src/commands/integration/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import { fetchInstallations } from '../../util/integration/fetch-installations';
import { fetchIntegration } from '../../util/integration/fetch-integration';
import output from '../../output-manager';
import { IntegrationAddTelemetryClient } from '../../util/telemetry/commands/integration/add';
import confirm from '../../util/input/confirm';

export async function add(client: Client, args: string[]) {
const telemetry = new IntegrationAddTelemetryClient({
Expand Down Expand Up @@ -139,8 +138,7 @@ export async function add(client: Client, args: string[]) {
return projectLink.exitCode;
}

const openInWeb = await confirm(
client,
const openInWeb = await client.input.confirm(
!installation
? 'Terms have not been accepted. Open Vercel Dashboard?'
: 'This resource must be provisioned through the Web UI. Open Vercel Dashboard?',
Expand Down Expand Up @@ -175,8 +173,7 @@ async function getOptionalLinkedProject(client: Client) {
return;
}

const shouldLinkToProject = await confirm(
client,
const shouldLinkToProject = await client.input.confirm(
'Do you want to link this resource to the current project?',
true
);
Expand Down Expand Up @@ -375,7 +372,7 @@ async function confirmProductSelection(
`${chalk.dim(`- ${chalk.bold('Plan:')} ${billingPlan.name}`)}\n`
);

return confirm(client, 'Confirm selection?', true);
return client.input.confirm('Confirm selection?', true);
}

async function provisionStorageProduct(
Expand Down
3 changes: 1 addition & 2 deletions packages/cli/src/commands/integration/remove-integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { parseArguments } from '../../util/get-args';
import { getFlagsSpecification } from '../../util/get-flags-specification';
import getScope from '../../util/get-scope';
import { printError } from '../../util/error';
import confirm from '../../util/input/confirm';
import { getFirstConfiguration } from '../../util/integration/fetch-marketplace-integrations';
import { removeIntegration } from '../../util/integration/remove-integration';
import { removeSubcommand } from './command';
Expand Down Expand Up @@ -102,5 +101,5 @@ async function confirmIntegrationRemoval(
output.log(
`The ${chalk.bold(integration)} integration will be removed permanently from team ${chalk.bold(team.name)}.`
);
return confirm(client, `${chalk.red('Are you sure?')}`, false);
return client.input.confirm(`${chalk.red('Are you sure?')}`, false);
}
6 changes: 4 additions & 2 deletions packages/cli/src/commands/project/rm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import ms from 'ms';
import type Client from '../../util/client';
import { emoji, prependEmoji } from '../../util/emoji';
import { isAPIError } from '../../util/errors-ts';
import confirm from '../../util/input/confirm';
import { getCommandName } from '../../util/pkg-name';
import { ProjectRmTelemetryClient } from '../../util/telemetry/commands/project/rm';
import output from '../../output-manager';
Expand Down Expand Up @@ -87,5 +86,8 @@ async function readConfirmation(
)
);

return await confirm(client, `${chalk.bold.red('Are you sure?')}`, false);
return await client.input.confirm(
`${chalk.bold.red('Are you sure?')}`,
false
);
}
3 changes: 1 addition & 2 deletions packages/cli/src/commands/promote/request-promote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { getCommandName } from '../../util/pkg-name';
import getProjectByDeployment from '../../util/projects/get-project-by-deployment';
import ms from 'ms';
import promoteStatus from './status';
import confirm from '../../util/input/confirm';
import output from '../../output-manager';

interface DeploymentCreateResponsePartial {
Expand Down Expand Up @@ -41,7 +40,7 @@ export default async function requestPromote({
} else {
const question =
'This deployment is not a production deployment and cannot be directly promoted. A new deployment will be built using your production environment. Are you sure you want to continue?';
promoteByCreation = await confirm(client, question, false);
promoteByCreation = await client.input.confirm(question, false);
if (!promoteByCreation) {
output.error('Canceled');
return 0;
Expand Down
7 changes: 5 additions & 2 deletions packages/cli/src/util/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,11 @@ export default class Client extends EventEmitter implements Stdio {
),
expand: (opts: Parameters<typeof expand>[0]) =>
expand({ theme, ...opts }, { input: this.stdin, output: this.stderr }),
confirm: (opts: Parameters<typeof confirm>[0]) =>
confirm({ theme, ...opts }, { input: this.stdin, output: this.stderr }),
confirm: (message: string, default_value: boolean) =>
confirm(
{ theme, message, default: default_value },
{ input: this.stdin, output: this.stderr }
),
select: <T>(opts: Parameters<typeof select<T>>[0]) =>
select<T>(
{ theme, ...opts },
Expand Down
3 changes: 1 addition & 2 deletions packages/cli/src/util/dns/get-dns-data.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import chalk from 'chalk';
import type { DNSRecordData } from '@vercel-internals/types';
import confirm from '../input/confirm';
import type Client from '../client';
import output from '../../output-manager';

Expand Down Expand Up @@ -88,7 +87,7 @@ export default async function getDNSData(
}

async function verifyData(client: Client) {
return confirm(client, 'Is this correct?', false);
return client.input.confirm('Is this correct?', false);
}

async function getRecordName(client: Client, type: string) {
Expand Down
Loading

0 comments on commit 2378fd6

Please sign in to comment.