diff options
Diffstat (limited to 'packages/turbo-workspaces/src/commands')
5 files changed, 222 insertions, 0 deletions
diff --git a/packages/turbo-workspaces/src/commands/convert/index.ts b/packages/turbo-workspaces/src/commands/convert/index.ts new file mode 100644 index 0000000..6cc82fc --- /dev/null +++ b/packages/turbo-workspaces/src/commands/convert/index.ts @@ -0,0 +1,109 @@ +import { ConvertCommandArgument, ConvertCommandOptions } from "./types"; +import inquirer from "inquirer"; +import { Logger } from "../../logger"; +import chalk from "chalk"; +import { getAvailablePackageManagers } from "@turbo/utils"; +import { directoryInfo } from "../../utils"; +import getWorkspaceDetails from "../../getWorkspaceDetails"; +import { PackageManager } from "../../types"; +import { convertProject } from "../../convert"; + +function isPackageManagerDisabled({ + packageManager, + currentWorkspaceManger, + availablePackageManagers, +}: { + packageManager: PackageManager; + currentWorkspaceManger: PackageManager; + availablePackageManagers: Record<PackageManager, { available: boolean }>; +}) { + if (currentWorkspaceManger === packageManager) { + return "already in use"; + } + + if (!availablePackageManagers[packageManager].available) { + return "not installed"; + } + + return false; +} + +export default async function convertCommand( + directory: ConvertCommandArgument, + packageManager: ConvertCommandArgument, + options: ConvertCommandOptions +) { + const logger = new Logger(options); + + logger.hero(); + logger.header("Welcome, let's convert your project."); + logger.blankLine(); + + const directoryAnswer = await inquirer.prompt<{ + directoryInput: string; + }>({ + type: "input", + name: "directoryInput", + message: "Where is the root of your repo?", + when: !directory, + default: ".", + validate: (directory: string) => { + const { exists, absolute } = directoryInfo({ directory }); + if (exists) { + return true; + } else { + return `Directory ${chalk.dim(`(${absolute})`)} does not exist`; + } + }, + filter: (directory: string) => directory.trim(), + }); + + const { directoryInput: selectedDirectory = directory } = directoryAnswer; + const { exists, absolute: root } = directoryInfo({ + directory: selectedDirectory, + }); + if (!exists) { + console.error(`Directory ${chalk.dim(`(${root})`)} does not exist`); + return process.exit(1); + } + + const [project, availablePackageManagers] = await Promise.all([ + getWorkspaceDetails({ root }), + getAvailablePackageManagers(), + ]); + + const packageManagerAnswer = await inquirer.prompt<{ + packageManagerInput?: PackageManager; + }>({ + name: "packageManagerInput", + type: "list", + message: `Convert from ${project.packageManager} workspaces to:`, + when: + !packageManager || + !Object.keys(availablePackageManagers).includes(packageManager), + choices: ["npm", "pnpm", "yarn"].map((p) => ({ + name: `${p} workspaces`, + value: p, + disabled: isPackageManagerDisabled({ + packageManager: p as PackageManager, + currentWorkspaceManger: project.packageManager, + availablePackageManagers, + }), + })), + }); + const { + packageManagerInput: + selectedPackageManager = packageManager as PackageManager, + } = packageManagerAnswer; + + await convertProject({ + project, + to: { + name: selectedPackageManager, + version: availablePackageManagers[selectedPackageManager] + .version as string, + }, + logger, + options, + }); +} diff --git a/packages/turbo-workspaces/src/commands/convert/types.ts b/packages/turbo-workspaces/src/commands/convert/types.ts new file mode 100644 index 0000000..a7b9deb --- /dev/null +++ b/packages/turbo-workspaces/src/commands/convert/types.ts @@ -0,0 +1,6 @@ +export type ConvertCommandArgument = string; +export type ConvertCommandOptions = { + dry: boolean; + force: boolean; + skipInstall: boolean; +}; diff --git a/packages/turbo-workspaces/src/commands/index.ts b/packages/turbo-workspaces/src/commands/index.ts new file mode 100644 index 0000000..423e959 --- /dev/null +++ b/packages/turbo-workspaces/src/commands/index.ts @@ -0,0 +1,8 @@ +export { default as summary } from "./summary"; +export { default as convert } from "./convert"; + +export type { SummaryCommandArgument } from "./summary/types"; +export type { + ConvertCommandArgument, + ConvertCommandOptions, +} from "./convert/types"; diff --git a/packages/turbo-workspaces/src/commands/summary/index.ts b/packages/turbo-workspaces/src/commands/summary/index.ts new file mode 100644 index 0000000..9696a14 --- /dev/null +++ b/packages/turbo-workspaces/src/commands/summary/index.ts @@ -0,0 +1,98 @@ +import inquirer from "inquirer"; +import path from "path"; +import { Logger } from "../../logger"; +import chalk from "chalk"; +import { SummaryCommandArgument } from "./types"; +import { directoryInfo } from "../../utils"; +import getWorkspaceDetails from "../../getWorkspaceDetails"; +import { Workspace } from "../../types"; + +export default async function summary(directory: SummaryCommandArgument) { + const logger = new Logger(); + logger.hero(); + + const answer = await inquirer.prompt<{ + directoryInput?: string; + }>({ + type: "input", + name: "directoryInput", + message: "Where is the root of the repo?", + when: !directory, + default: ".", + validate: (directory: string) => { + const { exists, absolute } = directoryInfo({ directory }); + if (exists) { + return true; + } else { + return `Directory ${chalk.dim(`(${absolute})`)} does not exist`; + } + }, + filter: (directory: string) => directory.trim(), + }); + + const { directoryInput: selectedDirectory = directory as string } = answer; + const { exists, absolute: root } = directoryInfo({ + directory: selectedDirectory, + }); + if (!exists) { + console.error(`Directory ${chalk.dim(`(${root})`)} does not exist`); + return process.exit(1); + } + + const project = await getWorkspaceDetails({ root }); + + const numWorkspaces = project.workspaceData.workspaces.length; + const hasWorkspaces = numWorkspaces > 0; + // group workspaces + const workspacesByDirectory: Record<string, Array<Workspace>> = {}; + project.workspaceData.workspaces.forEach((workspace) => { + const workspacePath = path.relative(root, workspace.paths.root); + const rootDirectory = workspacePath.split(path.sep)[0]; + if (!workspacesByDirectory[rootDirectory]) { + workspacesByDirectory[rootDirectory] = []; + } + workspacesByDirectory[rootDirectory].push(workspace); + }); + + const renderWorkspace = (w: Workspace) => { + return `${w.name} (${chalk.italic( + `./${path.relative(root, w.paths.root)}` + )})`; + }; + + const renderDirectory = ({ + number, + directory, + workspaces, + }: { + number: number; + directory: string; + workspaces: Array<Workspace>; + }) => { + logger.indented(2, `${number}. ${chalk.bold(directory)}`); + workspaces.forEach((workspace, idx) => { + logger.indented(3, `${idx + 1}. ${renderWorkspace(workspace)}`); + }); + }; + + // repo header + logger.header(`Repository Summary`); + logger.indented(1, `${chalk.underline(project.name)}:`); + // workspace manager header + logger.indented( + 1, + `Package Manager: ${chalk.bold(chalk.italic(project.packageManager))}` + ); + if (hasWorkspaces) { + // workspaces header + logger.indented(1, `Workspaces (${chalk.bold(numWorkspaces.toString())}):`); + Object.keys(workspacesByDirectory).forEach((directory, idx) => { + renderDirectory({ + number: idx + 1, + directory, + workspaces: workspacesByDirectory[directory], + }); + }); + logger.blankLine(); + } +} diff --git a/packages/turbo-workspaces/src/commands/summary/types.ts b/packages/turbo-workspaces/src/commands/summary/types.ts new file mode 100644 index 0000000..0cc5830 --- /dev/null +++ b/packages/turbo-workspaces/src/commands/summary/types.ts @@ -0,0 +1 @@ +export type SummaryCommandArgument = string; |
