Skip to content

Commit

Permalink
[cli] Refactor vc switch command (#6257)
Browse files Browse the repository at this point in the history
Refactors the `vc switch` command to more closely match how the team picker works on the Vercel dashboard:

 * Converts to TypeScript
 * Adds separator between user scope and team scopes
 * Sorts teams by name
 * No longer places the current scope at the top of the list (but the current scope is still selected by default)
  • Loading branch information
TooTallNate committed May 20, 2021
1 parent 711da37 commit 7b509ae
Show file tree
Hide file tree
Showing 11 changed files with 280 additions and 308 deletions.
1 change: 0 additions & 1 deletion packages/cli/@types/inquirer/index.d.ts

This file was deleted.

1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"@types/fs-extra": "5.0.5",
"@types/glob": "7.1.1",
"@types/http-proxy": "1.16.2",
"@types/inquirer": "7.3.1",
"@types/load-json-file": "2.0.7",
"@types/mime-types": "2.1.0",
"@types/minimatch": "3.0.3",
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/commands/init/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ async function chooseFromDropdown(message: string, exampleList: string[]) {

return listInput({
message,
separator: false,
choices,
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import chalk from 'chalk';
import error from '../util/output/error';
import NowTeams from '../util/teams';
import logo from '../util/output/logo';
import list from './teams/list';
import add from './teams/add';
import change from './teams/switch';
import invite from './teams/invite';
import { getPkgName } from '../util/pkg-name.ts';
import getArgs from '../util/get-args.ts';
import handleError from '../util/handle-error.ts';
import error from '../../util/output/error';
import NowTeams from '../../util/teams';
import logo from '../../util/output/logo';
import list from './list';
import add from './add';
import change from './switch';
import invite from './invite';
import { getPkgName } from '../../util/pkg-name';
import getArgs from '../../util/get-args';
import handleError from '../../util/handle-error';
import Client from '../../util/client';

const help = () => {
console.log(`
Expand Down Expand Up @@ -65,7 +66,7 @@ let debug;
let apiUrl;
let subcommand;

const main = async client => {
export default async (client: Client) => {
try {
argv = getArgs(client.argv.slice(2), {
'--since': String,
Expand Down Expand Up @@ -113,7 +114,7 @@ const main = async client => {
}
case 'switch':
case 'change': {
exitCode = await change(client, argv);
exitCode = await change(client, argv._[0]);
break;
}
case 'add':
Expand All @@ -139,13 +140,3 @@ const main = async client => {
teams.close();
return exitCode || 0;
};

export default async client => {
try {
return await main(client);
} catch (err) {
console.error(err);
handleError(err);
return 1;
}
};
190 changes: 0 additions & 190 deletions packages/cli/src/commands/teams/switch.js

This file was deleted.

123 changes: 123 additions & 0 deletions packages/cli/src/commands/teams/switch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Packages
import chalk from 'chalk';

// Utilities
import Client from '../../util/client';
import listInput from '../../util/input/list';
import getUser from '../../util/get-user';
import getTeams from '../../util/get-teams';
import { Team, GlobalConfig } from '../../types';
import { writeToConfigFile } from '../../util/config/files';

const updateCurrentTeam = (config: GlobalConfig, team?: Team) => {
if (team) {
config.currentTeam = team.id;
} else {
delete config.currentTeam;
}

writeToConfigFile(config);
};

export default async function main(client: Client, desiredSlug?: string) {
const { config, output } = client;
const personalScopeSelected = !config.currentTeam;

output.spinner('Fetching teams information');
const [user, teams] = await Promise.all([getUser(client), getTeams(client)]);

const currentTeam = personalScopeSelected
? undefined
: teams.find(team => team.id === config.currentTeam);

if (!personalScopeSelected && !currentTeam) {
output.error(`You are not a part of the current team anymore.`);
return 1;
}

if (!desiredSlug) {
const teamChoices = teams
.slice(0)
.sort((a, b) => {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
})
.map(({ id, slug, name }) => {
let title = `${name} (${slug})`;
const selected = id === currentTeam?.id;

if (selected) {
title += ` ${chalk.bold('(current)')}`;
}

return {
name: title,
value: slug,
short: slug,
selected,
};
});

// Add the User scope entry at the top
const suffix = personalScopeSelected ? ` ${chalk.bold('(current)')}` : '';

const choices = [
{ separator: 'Personal Account' },
{
name: `${user.email} (${user.username})${suffix}`,
value: user.email,
short: user.username,
selected: personalScopeSelected,
},
{ separator: 'Teams' },
...teamChoices,
];

output.stopSpinner();
desiredSlug = await listInput({
message: 'Switch to:',
choices,
eraseFinalAnswer: true,
});
}

// Abort
if (!desiredSlug) {
output.log('No changes made.');
return 0;
}

if (desiredSlug === user.username || desiredSlug === user.email) {
// Switch to user's personal account
if (personalScopeSelected) {
output.log('No changes made');
return 0;
}

updateCurrentTeam(config);

output.success(`Your account (${chalk.bold(desiredSlug)}) is now active!`);
return 0;
}

// Switch to selected team
const newTeam = teams.find(team => team.slug === desiredSlug);

if (!newTeam) {
output.error(
`You do not have permission to access scope ${chalk.bold(desiredSlug)}.`
);
return 1;
}

if (newTeam.slug === currentTeam?.slug) {
output.log('No changes made');
return 0;
}

updateCurrentTeam(config, newTeam);

output.success(
`The team ${chalk.bold(newTeam.name)} (${newTeam.slug}) is now active!`
);
return 0;
}

0 comments on commit 7b509ae

Please sign in to comment.