All files / src/commands/profile profile.switch.command.js

100% Statements 84/84
100% Branches 21/21
100% Functions 2/2
100% Lines 84/84

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 193x 9x 1x 1x 8x 8x 1x 1x 7x 7x 7x 1x 1x 1x 1x 6x 6x 5x 1x 1x 1x 4x 4x 4x 193x 193x 193x 193x 193x 193x 193x 193x 193x 6x 6x 4x 4x 1x 1x 1x 1x 1x 3x 3x 2x 2x 1x 1x 1x 1x 1x 3x 3x 1x 1x 1x 1x 1x 1x 1x 6x  
import { z } from 'zod';
import { config, saveProfile } from '../../config/config.js';
import { defineCommand } from '../../lib/define-command.js';
import { defineOption } from '../../lib/define-option.js';
import { formatProfile } from '../../lib/profile.js';
import { selectAnswer } from '../../lib/prompts.js';
import { styleText } from '../../lib/style-text.js';
import { Logger } from '../../logger.js';
 
/** @typedef {import('../../config/config.js').Profile} Profile */
 
export const profileSwitchCommand = defineCommand({
  description: 'Switch to a different profile',
  since: '4.6.0',
  options: {
    alias: defineOption({
      name: 'alias',
      aliases: ['a'],
      schema: z.string().optional(),
      description: 'Alias of the profile to switch to',
      placeholder: 'alias',
    }),
  },
  async handler(options) {
    if (config.profiles.length === 0) {
      throw new Error('No profile found.');
    }
 
    if (config.profiles.length === 1) {
      throw new Error('Only one profile. Use clever login --alias <name> to add another.');
    }
 
    const [activeProfile] = config.profiles;
    if (activeProfile.alias === '$env') {
      throw new Error(
        `Cannot switch profiles while using environment-based authentication, unset ${styleText('red', 'CLEVER_TOKEN')} and ${styleText('red', 'CLEVER_SECRET')} instead`,
      );
    }
 
    const targetProfile = await resolveTargetProfile(config.profiles, options.alias);
    if (targetProfile.alias === activeProfile.alias) {
      Logger.printInfo(`Already on profile ${styleText('blue', formatProfile(activeProfile))}`);
      return;
    }
 
    await saveProfile(targetProfile);
    Logger.printSuccess(`Switched to profile ${styleText('green', formatProfile(targetProfile))}`);
  },
});
 
/**
 * Resolve the target profile to switch to.
 * @param {Profile[]} profiles
 * @param {string | undefined} requestedAlias
 * @returns {Promise<Profile>}
 */
async function resolveTargetProfile(profiles, requestedAlias) {
  if (requestedAlias != null) {
    const targetProfile = profiles.find((p) => p.alias === requestedAlias);
    if (targetProfile == null) {
      const availableAliases = profiles.map((p) => p.alias).join(', ');
      throw new Error(
        `Profile "${styleText('red', requestedAlias)}" not found. Available profiles: ${availableAliases}`,
      );
    }
    return targetProfile;
  }
 
  if (profiles.length === 2) {
    Logger.printInfo(`Switching to ${styleText('blue', formatProfile(profiles[1]))}`);
    return profiles[1];
  }
 
  const choices = profiles.map((profile) => ({
    name: formatProfile(profile),
    value: profile.alias,
  }));
  const selectedAlias = await selectAnswer(
    'Select a profile:',
    choices,
    'Use --alias <name> to select a profile directly.',
  );
  return profiles.find((profile) => profile.alias === selectedAlias);
}