diff options
| author | 2023-11-03 21:25:40 +0800 | |
|---|---|---|
| committer | 2023-11-03 21:25:40 +0800 | |
| commit | 9029588590bea8b10451575c5142dcde77ecd1b5 (patch) | |
| tree | 04cf8aee56c23fd225ff19d340f7cee621d874ef /packages/turbo-workspaces/src | |
| parent | 94071d7ce16c56641d67d488e2bac6be84ffe731 (diff) | |
| download | HydroRoll-9029588590bea8b10451575c5142dcde77ecd1b5.tar.gz HydroRoll-9029588590bea8b10451575c5142dcde77ecd1b5.zip | |
chore: delete useless files
Diffstat (limited to 'packages/turbo-workspaces/src')
19 files changed, 0 insertions, 1847 deletions
diff --git a/packages/turbo-workspaces/src/cli.ts b/packages/turbo-workspaces/src/cli.ts deleted file mode 100644 index 3ae7a45..0000000 --- a/packages/turbo-workspaces/src/cli.ts +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env node - -import chalk from "chalk"; -import { Command } from "commander"; - -import { summary, convert } from "./commands"; -import cliPkg from "../package.json"; -import { ConvertError } from "./errors"; - -const workspacesCli = new Command(); - -workspacesCli - .name("@turbo/workspaces") - .description("Tools for working with package manager workspaces") - .version(cliPkg.version, "-v, --version", "output the current version"); - -// convert -workspacesCli - .command("convert") - .description("Convert project between workspace managers") - .argument("[path]", "Project root") - .argument("[package-manager]", "Package manager to convert to") - .option( - "--skip-install", - "Do not run a package manager install after conversion", - false - ) - .option("--dry", "Dry run (no changes are made to files)", false) - .option( - "--force", - "Bypass Git safety checks and forcibly run conversion", - false - ) - .action(convert); - -// summary -workspacesCli - .command("summary") - .description("Display a summary of the specified project") - .argument("[path]", "Project root") - .action(summary); - -workspacesCli.parseAsync().catch((error) => { - console.log(); - if (error instanceof ConvertError) { - console.log(chalk.red(error.message)); - } else { - console.log(chalk.red("Unexpected error. Please report it as a bug:")); - console.log(error.message); - } - console.log(); - process.exit(1); -}); diff --git a/packages/turbo-workspaces/src/commands/convert/index.ts b/packages/turbo-workspaces/src/commands/convert/index.ts deleted file mode 100644 index 6cc82fc..0000000 --- a/packages/turbo-workspaces/src/commands/convert/index.ts +++ /dev/null @@ -1,109 +0,0 @@ -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 deleted file mode 100644 index a7b9deb..0000000 --- a/packages/turbo-workspaces/src/commands/convert/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 423e959..0000000 --- a/packages/turbo-workspaces/src/commands/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index 9696a14..0000000 --- a/packages/turbo-workspaces/src/commands/summary/index.ts +++ /dev/null @@ -1,98 +0,0 @@ -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 deleted file mode 100644 index 0cc5830..0000000 --- a/packages/turbo-workspaces/src/commands/summary/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type SummaryCommandArgument = string; diff --git a/packages/turbo-workspaces/src/convert.ts b/packages/turbo-workspaces/src/convert.ts deleted file mode 100644 index 9f481c1..0000000 --- a/packages/turbo-workspaces/src/convert.ts +++ /dev/null @@ -1,61 +0,0 @@ -import chalk from "chalk"; -import managers from "./managers"; -import { Project, Options, PackageManagerDetails } from "./types"; -import install from "./install"; -import { Logger } from "./logger"; -import { ConvertError } from "./errors"; - -/* - * Convert a project using workspaces from one package manager to another. - - Steps are run in the following order: - 1. managerFrom.remove - 2. managerTo.create - 3. managerTo.convertLock - 3. install - 4. managerFrom.clean - -*/ -export async function convertProject({ - project, - to, - logger, - options, -}: { - project: Project; - to: PackageManagerDetails; - logger: Logger; - options?: Options; -}) { - logger.header( - `Converting project from ${project.packageManager} to ${to.name}.` - ); - - if (project.packageManager == to.name) { - throw new ConvertError("You are already using this package manager", { - type: "package_manager-already_in_use", - }); - } - - // remove old workspace data - await managers[project.packageManager].remove({ - project, - to, - logger, - options, - }); - - // create new workspace data - await managers[to.name].create({ project, to, logger, options }); - - logger.mainStep("Installing dependencies"); - if (!options?.skipInstall) { - await managers[to.name].convertLock({ project, logger, options }); - await install({ project, to, logger, options }); - } else { - logger.subStep(chalk.yellow("Skipping install")); - } - - logger.mainStep(`Cleaning up ${project.packageManager} workspaces`); - await managers[project.packageManager].clean({ project, logger }); -} diff --git a/packages/turbo-workspaces/src/errors.ts b/packages/turbo-workspaces/src/errors.ts deleted file mode 100644 index aa2fabe..0000000 --- a/packages/turbo-workspaces/src/errors.ts +++ /dev/null @@ -1,31 +0,0 @@ -export type ConvertErrorType = - // package manager general - | "package_manager-unexpected" - | "package_manager-already_in_use" - | "package_manager-unable_to_detect" - | "package_manager-unsupported_version" - // package manager specific - | "pnpm-workspace_parse_error" - // package.json - | "package_json-parse_error" - | "package_json-missing" - // other - | "invalid_directory" - | "error_removing_node_modules" - // default - | "unknown"; - -export type ConvertErrorOptions = { - type?: ConvertErrorType; -}; - -export class ConvertError extends Error { - public type: ConvertErrorType; - - constructor(message: string, opts?: ConvertErrorOptions) { - super(message); - this.name = "ConvertError"; - this.type = opts?.type ?? "unknown"; - Error.captureStackTrace(this, ConvertError); - } -} diff --git a/packages/turbo-workspaces/src/getWorkspaceDetails.ts b/packages/turbo-workspaces/src/getWorkspaceDetails.ts deleted file mode 100644 index ad86a97..0000000 --- a/packages/turbo-workspaces/src/getWorkspaceDetails.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ConvertError } from "./errors"; -import managers from "./managers"; -import { Project } from "./types"; -import { directoryInfo } from "./utils"; - -export default async function getWorkspaceDetails({ - root, -}: { - root: string; -}): Promise<Project> { - const { exists, absolute: workspaceRoot } = directoryInfo({ - directory: root, - }); - if (!exists) { - throw new ConvertError( - `Could not find directory at ${workspaceRoot}. Ensure the directory exists.`, - { - type: "invalid_directory", - } - ); - } - - for (const { detect, read } of Object.values(managers)) { - if (await detect({ workspaceRoot })) { - return read({ workspaceRoot }); - } - } - - throw new ConvertError( - "Could not determine package manager. Add `packageManager` to `package.json` or ensure a lockfile is present.", - { - type: "package_manager-unable_to_detect", - } - ); -} diff --git a/packages/turbo-workspaces/src/index.ts b/packages/turbo-workspaces/src/index.ts deleted file mode 100644 index c7fc6b8..0000000 --- a/packages/turbo-workspaces/src/index.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { getAvailablePackageManagers } from "@turbo/utils"; -import getWorkspaceDetails from "./getWorkspaceDetails"; -import { convertProject } from "./convert"; -import { Logger } from "./logger"; -import install, { getPackageManagerMeta } from "./install"; -import { ConvertError } from "./errors"; -import MANAGERS from "./managers"; - -import type { - PackageManager, - Options, - InstallArgs, - Workspace, - Project, -} from "./types"; -import type { ConvertErrorType } from "./errors"; - -async function convert({ - root, - to, - options, -}: { - root: string; - to: PackageManager; - options?: Options; -}) { - const logger = new Logger({ ...options, interactive: false }); - const [project, availablePackageManagers] = await Promise.all([ - getWorkspaceDetails({ root }), - getAvailablePackageManagers(), - ]); - await convertProject({ - project, - to: { - name: to, - version: availablePackageManagers[to].version as PackageManager, - }, - logger, - options, - }); -} - -export type { - PackageManager, - Options, - InstallArgs, - Workspace, - Project, - ConvertErrorType, -}; -export { - convert, - getWorkspaceDetails, - install, - MANAGERS, - getPackageManagerMeta, - ConvertError, -}; diff --git a/packages/turbo-workspaces/src/install.ts b/packages/turbo-workspaces/src/install.ts deleted file mode 100644 index ad5f741..0000000 --- a/packages/turbo-workspaces/src/install.ts +++ /dev/null @@ -1,125 +0,0 @@ -import execa from "execa"; -import ora from "ora"; -import { satisfies } from "semver"; -import { ConvertError } from "./errors"; -import { Logger } from "./logger"; -import { - PackageManager, - PackageManagerDetails, - PackageManagerInstallDetails, - InstallArgs, -} from "./types"; - -export const PACKAGE_MANAGERS: Record< - PackageManager, - Array<PackageManagerInstallDetails> -> = { - npm: [ - { - name: "npm", - template: "npm", - command: "npm", - installArgs: ["install"], - version: "latest", - executable: "npx", - semver: "*", - default: true, - }, - ], - pnpm: [ - { - name: "pnpm6", - template: "pnpm", - command: "pnpm", - installArgs: ["install"], - version: "latest-6", - executable: "pnpx", - semver: "6.x", - }, - { - name: "pnpm", - template: "pnpm", - command: "pnpm", - installArgs: ["install"], - version: "latest", - executable: "pnpm dlx", - semver: ">=7", - default: true, - }, - ], - yarn: [ - { - name: "yarn", - template: "yarn", - command: "yarn", - installArgs: ["install"], - version: "1.x", - executable: "npx", - semver: "<2", - default: true, - }, - { - name: "berry", - template: "berry", - command: "yarn", - installArgs: ["install", "--no-immutable"], - version: "stable", - executable: "yarn dlx", - semver: ">=2", - }, - ], -}; - -export function getPackageManagerMeta(packageManager: PackageManagerDetails) { - const { version, name } = packageManager; - if (version) { - return PACKAGE_MANAGERS[name].find((manager) => - satisfies(version, manager.semver) - ); - } else { - return PACKAGE_MANAGERS[name].find((manager) => { - return manager.default; - }); - } -} - -export default async function install(args: InstallArgs) { - const { to, logger, options } = args; - - const installLogger = logger ?? new Logger(options); - const packageManager = getPackageManagerMeta(to); - - if (!packageManager) { - throw new ConvertError("Unsupported package manager version.", { - type: "package_manager-unsupported_version", - }); - } - - installLogger.subStep( - `running "${packageManager.command} ${packageManager.installArgs}"` - ); - if (!options?.dry) { - let spinner; - if (installLogger?.interactive) { - spinner = ora({ - text: "installing dependencies...", - spinner: { - frames: installLogger.installerFrames(), - }, - }).start(); - } - - try { - await execa(packageManager.command, packageManager.installArgs, { - cwd: args.project.paths.root, - }); - if (spinner) { - spinner.stop(); - } - installLogger.subStep(`dependencies installed`); - } catch (err) { - installLogger.subStepFailure(`failed to install dependencies`); - throw err; - } - } -} diff --git a/packages/turbo-workspaces/src/logger.ts b/packages/turbo-workspaces/src/logger.ts deleted file mode 100644 index 222c89a..0000000 --- a/packages/turbo-workspaces/src/logger.ts +++ /dev/null @@ -1,109 +0,0 @@ -import chalk from "chalk"; -import gradient from "gradient-string"; - -const INDENTATION = 2; - -export class Logger { - interactive: boolean; - dry: boolean; - step: number; - - constructor({ - interactive, - dry, - }: { interactive?: boolean; dry?: boolean } = {}) { - this.interactive = interactive ?? true; - this.dry = dry ?? false; - this.step = 1; - } - - logger(...args: any[]) { - if (this.interactive) { - console.log(...args); - } - } - - indented(level: number, ...args: any[]) { - this.logger(" ".repeat(INDENTATION * level), ...args); - } - - header(title: string) { - this.blankLine(); - this.logger(chalk.bold(title)); - } - - installerFrames() { - const prefix = `${" ".repeat(INDENTATION)} - ${ - this.dry ? chalk.yellow("SKIPPED | ") : chalk.green("OK | ") - }`; - return [`${prefix} `, `${prefix}> `, `${prefix}>> `, `${prefix}>>>`]; - } - - gradient(text: string | number) { - const turboGradient = gradient("#0099F7", "#F11712"); - return turboGradient(text.toString()); - } - - hero() { - this.logger(chalk.bold(this.gradient(`\n>>> TURBOREPO\n`))); - } - - info(...args: any[]) { - this.logger(...args); - } - - mainStep(title: string) { - this.blankLine(); - this.logger(`${this.step}. ${chalk.underline(title)}`); - this.step += 1; - } - - subStep(...args: any[]) { - this.logger( - " ".repeat(INDENTATION), - `-`, - this.dry ? chalk.yellow("SKIPPED |") : chalk.green("OK |"), - ...args - ); - } - - subStepFailure(...args: any[]) { - this.logger(" ".repeat(INDENTATION), `-`, chalk.red("ERROR |"), ...args); - } - - rootHeader() { - this.blankLine(); - this.indented(2, "Root:"); - } - - rootStep(...args: any[]) { - this.logger( - " ".repeat(INDENTATION * 3), - `-`, - this.dry ? chalk.yellow("SKIPPED |") : chalk.green("OK |"), - ...args - ); - } - - workspaceHeader() { - this.blankLine(); - this.indented(2, "Workspaces:"); - } - - workspaceStep(...args: any[]) { - this.logger( - " ".repeat(INDENTATION * 3), - `-`, - this.dry ? chalk.yellow("SKIPPED |") : chalk.green("OK |"), - ...args - ); - } - - blankLine() { - this.logger(); - } - - error(...args: any[]) { - console.error(...args); - } -} diff --git a/packages/turbo-workspaces/src/managers/index.ts b/packages/turbo-workspaces/src/managers/index.ts deleted file mode 100644 index e026aed..0000000 --- a/packages/turbo-workspaces/src/managers/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import pnpm from "./pnpm"; -import npm from "./npm"; -import yarn from "./yarn"; -import { ManagerHandler, PackageManager } from "../types"; - -const MANAGERS: Record<PackageManager, ManagerHandler> = { - pnpm, - yarn, - npm, -}; -export default MANAGERS; diff --git a/packages/turbo-workspaces/src/managers/npm.ts b/packages/turbo-workspaces/src/managers/npm.ts deleted file mode 100644 index 26fd76a..0000000 --- a/packages/turbo-workspaces/src/managers/npm.ts +++ /dev/null @@ -1,223 +0,0 @@ -import fs from "fs-extra"; -import path from "path"; -import { ConvertError } from "../errors"; -import updateDependencies from "../updateDependencies"; -import { - DetectArgs, - ReadArgs, - CreateArgs, - RemoveArgs, - CleanArgs, - Project, - ConvertArgs, - ManagerHandler, -} from "../types"; -import { - getMainStep, - getWorkspaceInfo, - getPackageJson, - expandWorkspaces, - getWorkspacePackageManager, - expandPaths, -} from "../utils"; - -/** - * Check if a given project is using npm workspaces - * Verify by checking for the existence of: - * 1. package-lock.json - * 2. packageManager field in package.json - */ -async function detect(args: DetectArgs): Promise<boolean> { - const lockFile = path.join(args.workspaceRoot, "package-lock.json"); - const packageManager = getWorkspacePackageManager({ - workspaceRoot: args.workspaceRoot, - }); - return fs.existsSync(lockFile) || packageManager === "npm"; -} - -/** - Read workspace data from npm workspaces into generic format -*/ -async function read(args: ReadArgs): Promise<Project> { - const isNpm = await detect(args); - if (!isNpm) { - throw new ConvertError("Not an npm project", { - type: "package_manager-unexpected", - }); - } - - const packageJson = getPackageJson(args); - const { name, description } = getWorkspaceInfo(args); - return { - name, - description, - packageManager: "npm", - paths: expandPaths({ - root: args.workspaceRoot, - lockFile: "package-lock.json", - }), - workspaceData: { - globs: packageJson.workspaces || [], - workspaces: expandWorkspaces({ - workspaceGlobs: packageJson.workspaces, - ...args, - }), - }, - }; -} - -/** - * Create npm workspaces from generic format - * - * Creating npm workspaces involves: - * 1. Adding the workspaces field in package.json - * 2. Setting the packageManager field in package.json - * 3. Updating all workspace package.json dependencies to ensure correct format - */ -async function create(args: CreateArgs): Promise<void> { - const { project, options, to, logger } = args; - const hasWorkspaces = project.workspaceData.globs.length > 0; - - logger.mainStep( - getMainStep({ packageManager: "npm", action: "create", project }) - ); - const packageJson = getPackageJson({ workspaceRoot: project.paths.root }); - logger.rootHeader(); - - // package manager - logger.rootStep( - `adding "packageManager" field to ${path.relative( - project.paths.root, - project.paths.packageJson - )}` - ); - packageJson.packageManager = `${to.name}@${to.version}`; - - if (hasWorkspaces) { - // workspaces field - logger.rootStep( - `adding "workspaces" field to ${path.relative( - project.paths.root, - project.paths.packageJson - )}` - ); - packageJson.workspaces = project.workspaceData.globs; - - // write package.json here instead of deferring to avoid negating the changes made by updateDependencies - if (!options?.dry) { - fs.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 }); - } - - // root dependencies - updateDependencies({ - workspace: { name: "root", paths: project.paths }, - project, - to, - logger, - options, - }); - - // workspace dependencies - logger.workspaceHeader(); - project.workspaceData.workspaces.forEach((workspace) => - updateDependencies({ workspace, project, to, logger, options }) - ); - } else { - if (!options?.dry) { - fs.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 }); - } - } -} - -/** - * Remove npm workspace data - * Removing npm workspaces involves: - * 1. Removing the workspaces field from package.json - * 2. Removing the node_modules directory - */ -async function remove(args: RemoveArgs): Promise<void> { - const { project, logger, options } = args; - const hasWorkspaces = project.workspaceData.globs.length > 0; - - logger.mainStep( - getMainStep({ packageManager: "npm", action: "remove", project }) - ); - const packageJson = getPackageJson({ workspaceRoot: project.paths.root }); - - if (hasWorkspaces) { - logger.subStep( - `removing "workspaces" field in ${project.name} root "package.json"` - ); - delete packageJson.workspaces; - } - - logger.subStep( - `removing "packageManager" field in ${project.name} root "package.json"` - ); - delete packageJson.packageManager; - - if (!options?.dry) { - fs.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 }); - - // collect all workspace node_modules directories - const allModulesDirs = [ - project.paths.nodeModules, - ...project.workspaceData.workspaces.map((w) => w.paths.nodeModules), - ]; - try { - logger.subStep(`removing "node_modules"`); - await Promise.all( - allModulesDirs.map((dir) => - fs.rm(dir, { recursive: true, force: true }) - ) - ); - } catch (err) { - throw new ConvertError("Failed to remove node_modules", { - type: "error_removing_node_modules", - }); - } - } -} - -/** - * Clean is called post install, and is used to clean up any files - * from this package manager that were needed for install, - * but not required after migration - */ -async function clean(args: CleanArgs): Promise<void> { - const { project, logger, options } = args; - - logger.subStep( - `removing ${path.relative(project.paths.root, project.paths.lockfile)}` - ); - if (!options?.dry) { - fs.rmSync(project.paths.lockfile, { force: true }); - } -} - -/** - * Attempts to convert an existing, non npm lockfile to an npm lockfile - * - * If this is not possible, the non npm lockfile is removed - */ -async function convertLock(args: ConvertArgs): Promise<void> { - const { project, options } = args; - - if (project.packageManager !== "npm") { - // remove the lockfile - if (!options?.dry) { - fs.rmSync(project.paths.lockfile, { force: true }); - } - } -} - -const npm: ManagerHandler = { - detect, - read, - create, - remove, - clean, - convertLock, -}; - -export default npm; diff --git a/packages/turbo-workspaces/src/managers/pnpm.ts b/packages/turbo-workspaces/src/managers/pnpm.ts deleted file mode 100644 index 747e578..0000000 --- a/packages/turbo-workspaces/src/managers/pnpm.ts +++ /dev/null @@ -1,238 +0,0 @@ -import fs from "fs-extra"; -import path from "path"; -import execa from "execa"; -import { ConvertError } from "../errors"; -import updateDependencies from "../updateDependencies"; -import { - DetectArgs, - ReadArgs, - CreateArgs, - RemoveArgs, - ConvertArgs, - CleanArgs, - Project, - ManagerHandler, -} from "../types"; -import { - getMainStep, - expandPaths, - getWorkspaceInfo, - expandWorkspaces, - getPnpmWorkspaces, - getPackageJson, - getWorkspacePackageManager, -} from "../utils"; - -/** - * Check if a given project is using pnpm workspaces - * Verify by checking for the existence of: - * 1. pnpm-workspace.yaml - * 2. pnpm-workspace.yaml - */ -async function detect(args: DetectArgs): Promise<boolean> { - const lockFile = path.join(args.workspaceRoot, "pnpm-lock.yaml"); - const workspaceFile = path.join(args.workspaceRoot, "pnpm-workspace.yaml"); - const packageManager = getWorkspacePackageManager({ - workspaceRoot: args.workspaceRoot, - }); - return ( - fs.existsSync(lockFile) || - fs.existsSync(workspaceFile) || - packageManager === "pnpm" - ); -} - -/** - Read workspace data from pnpm workspaces into generic format -*/ -async function read(args: ReadArgs): Promise<Project> { - const isPnpm = await detect(args); - if (!isPnpm) { - throw new ConvertError("Not a pnpm project", { - type: "package_manager-unexpected", - }); - } - - const { name, description } = getWorkspaceInfo(args); - return { - name, - description, - packageManager: "pnpm", - paths: expandPaths({ - root: args.workspaceRoot, - lockFile: "pnpm-lock.yaml", - workspaceConfig: "pnpm-workspace.yaml", - }), - workspaceData: { - globs: getPnpmWorkspaces(args), - workspaces: expandWorkspaces({ - workspaceGlobs: getPnpmWorkspaces(args), - ...args, - }), - }, - }; -} - -/** - * Create pnpm workspaces from generic format - * - * Creating pnpm workspaces involves: - * 1. Create pnpm-workspace.yaml - * 2. Setting the packageManager field in package.json - * 3. Updating all workspace package.json dependencies to ensure correct format - */ -async function create(args: CreateArgs): Promise<void> { - const { project, to, logger, options } = args; - const hasWorkspaces = project.workspaceData.globs.length > 0; - - logger.mainStep( - getMainStep({ action: "create", packageManager: "pnpm", project }) - ); - - const packageJson = getPackageJson({ workspaceRoot: project.paths.root }); - logger.rootHeader(); - packageJson.packageManager = `${to.name}@${to.version}`; - logger.rootStep( - `adding "packageManager" field to ${project.name} root "package.json"` - ); - - // write the changes - if (!options?.dry) { - fs.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 }); - - if (hasWorkspaces) { - logger.rootStep(`adding "pnpm-workspace.yaml"`); - fs.writeFileSync( - path.join(project.paths.root, "pnpm-workspace.yaml"), - `packages:\n${project.workspaceData.globs - .map((w) => ` - "${w}"`) - .join("\n")}` - ); - } - } - - if (hasWorkspaces) { - // root dependencies - updateDependencies({ - workspace: { name: "root", paths: project.paths }, - project, - to, - logger, - options, - }); - - // workspace dependencies - logger.workspaceHeader(); - project.workspaceData.workspaces.forEach((workspace) => - updateDependencies({ workspace, project, to, logger, options }) - ); - } -} - -/** - * Remove pnpm workspace data - * - * Cleaning up from pnpm involves: - * 1. Removing the pnpm-workspace.yaml file - * 2. Removing the pnpm-lock.yaml file - * 3. Removing the node_modules directory - */ -async function remove(args: RemoveArgs): Promise<void> { - const { project, logger, options } = args; - const hasWorkspaces = project.workspaceData.globs.length > 0; - - logger.mainStep( - getMainStep({ action: "remove", packageManager: "pnpm", project }) - ); - const packageJson = getPackageJson({ workspaceRoot: project.paths.root }); - - if (project.paths.workspaceConfig && hasWorkspaces) { - logger.subStep(`removing "pnpm-workspace.yaml"`); - if (!options?.dry) { - fs.rmSync(project.paths.workspaceConfig, { force: true }); - } - } - - logger.subStep( - `removing "packageManager" field in ${project.name} root "package.json"` - ); - delete packageJson.packageManager; - - if (!options?.dry) { - fs.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 }); - - // collect all workspace node_modules directories - const allModulesDirs = [ - project.paths.nodeModules, - ...project.workspaceData.workspaces.map((w) => w.paths.nodeModules), - ]; - - try { - logger.subStep(`removing "node_modules"`); - await Promise.all( - allModulesDirs.map((dir) => - fs.rm(dir, { recursive: true, force: true }) - ) - ); - } catch (err) { - throw new ConvertError("Failed to remove node_modules", { - type: "error_removing_node_modules", - }); - } - } -} - -/** - * Clean is called post install, and is used to clean up any files - * from this package manager that were needed for install, - * but not required after migration - */ -async function clean(args: CleanArgs): Promise<void> { - const { project, logger, options } = args; - - logger.subStep( - `removing ${path.relative(project.paths.root, project.paths.lockfile)}` - ); - if (!options?.dry) { - fs.rmSync(project.paths.lockfile, { force: true }); - } -} - -/** - * Attempts to convert an existing, non pnpm lockfile to a pnpm lockfile - * - * If this is not possible, the non pnpm lockfile is removed - */ -async function convertLock(args: ConvertArgs): Promise<void> { - const { project, logger, options } = args; - - if (project.packageManager !== "pnpm") { - logger.subStep( - `converting ${path.relative( - project.paths.root, - project.paths.lockfile - )} to pnpm-lock.yaml` - ); - if (!options?.dry && fs.existsSync(project.paths.lockfile)) { - try { - await execa("pnpm", ["import"], { - stdio: "ignore", - cwd: project.paths.root, - }); - } finally { - fs.rmSync(project.paths.lockfile, { force: true }); - } - } - } -} - -const pnpm: ManagerHandler = { - detect, - read, - create, - remove, - clean, - convertLock, -}; - -export default pnpm; diff --git a/packages/turbo-workspaces/src/managers/yarn.ts b/packages/turbo-workspaces/src/managers/yarn.ts deleted file mode 100644 index 9bef53f..0000000 --- a/packages/turbo-workspaces/src/managers/yarn.ts +++ /dev/null @@ -1,222 +0,0 @@ -import fs from "fs-extra"; -import path from "path"; -import { ConvertError } from "../errors"; -import updateDependencies from "../updateDependencies"; -import { - DetectArgs, - ReadArgs, - CreateArgs, - RemoveArgs, - ConvertArgs, - CleanArgs, - Project, -} from "../types"; -import { - getMainStep, - getWorkspaceInfo, - getPackageJson, - expandPaths, - expandWorkspaces, - getWorkspacePackageManager, -} from "../utils"; - -/** - * Check if a given project is using yarn workspaces - * Verify by checking for the existence of: - * 1. yarn.lock - * 2. packageManager field in package.json - */ -async function detect(args: DetectArgs): Promise<boolean> { - const lockFile = path.join(args.workspaceRoot, "yarn.lock"); - const packageManager = getWorkspacePackageManager({ - workspaceRoot: args.workspaceRoot, - }); - return fs.existsSync(lockFile) || packageManager === "yarn"; -} - -/** - Read workspace data from yarn workspaces into generic format -*/ -async function read(args: ReadArgs): Promise<Project> { - const isYarn = await detect(args); - if (!isYarn) { - throw new ConvertError("Not a yarn project", { - type: "package_manager-unexpected", - }); - } - - const packageJson = getPackageJson(args); - const { name, description } = getWorkspaceInfo(args); - return { - name, - description, - packageManager: "yarn", - paths: expandPaths({ - root: args.workspaceRoot, - lockFile: "yarn.lock", - }), - workspaceData: { - globs: packageJson.workspaces || [], - workspaces: expandWorkspaces({ - workspaceGlobs: packageJson.workspaces, - ...args, - }), - }, - }; -} - -/** - * Create yarn workspaces from generic format - * - * Creating yarn workspaces involves: - * 1. Adding the workspaces field in package.json - * 2. Setting the packageManager field in package.json - * 3. Updating all workspace package.json dependencies to ensure correct format - */ -async function create(args: CreateArgs): Promise<void> { - const { project, to, logger, options } = args; - const hasWorkspaces = project.workspaceData.globs.length > 0; - - logger.mainStep( - getMainStep({ packageManager: "yarn", action: "create", project }) - ); - const packageJson = getPackageJson({ workspaceRoot: project.paths.root }); - logger.rootHeader(); - - // package manager - logger.rootStep( - `adding "packageManager" field to ${path.relative( - project.paths.root, - project.paths.packageJson - )}` - ); - packageJson.packageManager = `${to.name}@${to.version}`; - - if (hasWorkspaces) { - // workspaces field - logger.rootStep( - `adding "workspaces" field to ${path.relative( - project.paths.root, - project.paths.packageJson - )}` - ); - packageJson.workspaces = project.workspaceData.globs; - - if (!options?.dry) { - fs.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 }); - } - - // root dependencies - updateDependencies({ - workspace: { name: "root", paths: project.paths }, - project, - to, - logger, - options, - }); - - // workspace dependencies - logger.workspaceHeader(); - project.workspaceData.workspaces.forEach((workspace) => - updateDependencies({ workspace, project, to, logger, options }) - ); - } else { - if (!options?.dry) { - fs.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 }); - } - } -} - -/** - * Remove yarn workspace data - * - * Removing yarn workspaces involves: - * 1. Removing the workspaces field from package.json - * 2. Removing the node_modules directory - */ -async function remove(args: RemoveArgs): Promise<void> { - const { project, logger, options } = args; - const hasWorkspaces = project.workspaceData.globs.length > 0; - - logger.mainStep( - getMainStep({ packageManager: "yarn", action: "remove", project }) - ); - const packageJson = getPackageJson({ workspaceRoot: project.paths.root }); - - if (hasWorkspaces) { - logger.subStep( - `removing "workspaces" field in ${project.name} root "package.json"` - ); - delete packageJson.workspaces; - } - - logger.subStep( - `removing "packageManager" field in ${project.name} root "package.json"` - ); - delete packageJson.packageManager; - - if (!options?.dry) { - fs.writeJSONSync(project.paths.packageJson, packageJson, { spaces: 2 }); - - // collect all workspace node_modules directories - const allModulesDirs = [ - project.paths.nodeModules, - ...project.workspaceData.workspaces.map((w) => w.paths.nodeModules), - ]; - try { - logger.subStep(`removing "node_modules"`); - await Promise.all( - allModulesDirs.map((dir) => - fs.rm(dir, { recursive: true, force: true }) - ) - ); - } catch (err) { - throw new ConvertError("Failed to remove node_modules", { - type: "error_removing_node_modules", - }); - } - } -} - -/** - * Clean is called post install, and is used to clean up any files - * from this package manager that were needed for install, - * but not required after migration - */ -async function clean(args: CleanArgs): Promise<void> { - const { project, logger, options } = args; - - logger.subStep( - `removing ${path.relative(project.paths.root, project.paths.lockfile)}` - ); - if (!options?.dry) { - fs.rmSync(project.paths.lockfile, { force: true }); - } -} - -/** - * Attempts to convert an existing, non yarn lockfile to a yarn lockfile - * - * If this is not possible, the non yarn lockfile is removed - */ -async function convertLock(args: ConvertArgs): Promise<void> { - const { project, options } = args; - - if (project.packageManager !== "yarn") { - // remove the lockfile - if (!options?.dry) { - fs.rmSync(project.paths.lockfile, { force: true }); - } - } -} - -const yarn = { - detect, - read, - create, - remove, - clean, - convertLock, -}; - -export default yarn; diff --git a/packages/turbo-workspaces/src/types.ts b/packages/turbo-workspaces/src/types.ts deleted file mode 100644 index 9240f09..0000000 --- a/packages/turbo-workspaces/src/types.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { Logger } from "./logger"; - -export type PackageManager = "npm" | "pnpm" | "yarn"; -export type PackageManagerDetails = { - name: PackageManager; - version?: string; -}; - -export type Project = { - name: string; - description?: string; - packageManager: PackageManager; - paths: { - root: string; - packageJson: string; - lockfile: string; - nodeModules: string; - // pnpm workspace config file - workspaceConfig?: string; - }; - workspaceData: { - globs: Array<string>; - workspaces: Array<Workspace>; - }; -}; - -export type Workspace = { - name: string; - description?: string; - paths: { - root: string; - packageJson: string; - nodeModules: string; - }; -}; - -export type WorkspaceInfo = Pick<Workspace, "name" | "description">; - -export type DependencyList = Record<string, string>; - -export type PackageJsonDependencies = { - dependencies?: DependencyList; - devDependencies?: DependencyList; - peerDependencies?: DependencyList; - optionalDependencies?: DependencyList; -}; - -export type PackageJson = PackageJsonDependencies & { - name?: string; - description?: string; - workspaces?: Array<string>; - packageManager?: string; -}; - -export type DetectArgs = { - workspaceRoot: string; -}; - -export type ReadArgs = { - workspaceRoot: string; -}; - -export type CreateArgs = { - project: Project; - to: PackageManagerDetails; - logger: Logger; - options?: Options; -}; - -export type RemoveArgs = { - project: Project; - to: PackageManagerDetails; - logger: Logger; - options?: Options; -}; - -export type CleanArgs = { - project: Project; - logger: Logger; - options?: Options; -}; - -export type ConvertArgs = { - project: Project; - logger: Logger; - options?: Options; -}; - -export type InstallArgs = { - project: Project; - to: PackageManagerDetails; - logger?: Logger; - options?: Options; -}; - -export type Options = { - dry?: boolean; - skipInstall?: boolean; - interactive?: boolean; -}; - -export type PackageManagerInstallDetails = { - name: string; - template: string; - command: PackageManager; - installArgs: string[]; - version: string; - executable: string; - semver: string; - default?: boolean; -}; - -export type ManagerDetect = (args: DetectArgs) => Promise<boolean>; -export type ManagerRead = (args: ReadArgs) => Promise<Project>; -export type ManagerCreate = (args: CreateArgs) => Promise<void>; -export type ManagerRemove = (args: RemoveArgs) => Promise<void>; -export type ManagerClean = (args: CleanArgs) => Promise<void>; -export type ManagerConvert = (args: ConvertArgs) => Promise<void>; - -export type ManagerHandler = { - detect: ManagerDetect; - read: ManagerRead; - create: ManagerCreate; - remove: ManagerRemove; - clean: ManagerClean; - convertLock: ManagerConvert; -}; diff --git a/packages/turbo-workspaces/src/updateDependencies.ts b/packages/turbo-workspaces/src/updateDependencies.ts deleted file mode 100644 index 5461ed0..0000000 --- a/packages/turbo-workspaces/src/updateDependencies.ts +++ /dev/null @@ -1,135 +0,0 @@ -import fs from "fs-extra"; -import chalk from "chalk"; -import path from "path"; -import { - Project, - Workspace, - DependencyList, - PackageManagerDetails, - Options, - PackageJsonDependencies, -} from "./types"; -import { Logger } from "./logger"; -import { getPackageJson } from "./utils"; - -function updateDependencyList({ - dependencyList, - project, - to, -}: { - dependencyList: DependencyList; - project: Project; - to: PackageManagerDetails; -}): { dependencyList: DependencyList; updated: Array<string> } { - const updated: Array<string> = []; - project.workspaceData.workspaces.forEach((workspace) => { - const { name } = workspace; - if (dependencyList[name]) { - const workspaceVersion = dependencyList[name]; - const version = workspaceVersion.startsWith("workspace:") - ? workspaceVersion.slice("workspace:".length) - : workspaceVersion; - dependencyList[name] = - to.name === "pnpm" ? `workspace:${version}` : version; - updated.push(name); - } - }); - - return { dependencyList, updated }; -} - -export default function updateDependencies({ - project, - workspace, - to, - logger, - options, -}: { - workspace: Workspace; - project: Project; - to: PackageManagerDetails; - logger: Logger; - options?: Options; -}): void { - // this step isn't required if moving between yarn / npm - if ( - ["yarn", "npm"].includes(to.name) && - ["yarn", "npm"].includes(project.packageManager) - ) { - return; - } - - // update all dependencies - const workspacePackageJson = getPackageJson({ - workspaceRoot: workspace.paths.root, - }); - - // collect stats as we go for consolidated output at the end - const stats: Record<keyof PackageJsonDependencies, Array<string>> = { - dependencies: [], - devDependencies: [], - peerDependencies: [], - optionalDependencies: [], - }; - - const allDependencyKeys: Array<keyof PackageJsonDependencies> = [ - "dependencies", - "devDependencies", - "peerDependencies", - "optionalDependencies", - ]; - - allDependencyKeys.forEach((depKey) => { - const depList = workspacePackageJson[depKey]; - if (depList) { - const { updated, dependencyList } = updateDependencyList({ - dependencyList: depList, - project, - to, - }); - - workspacePackageJson[depKey] = dependencyList; - stats[depKey] = updated; - } - }); - - const toLog = (key: keyof PackageJsonDependencies) => { - const total = stats[key].length; - if (total > 0) { - return `${chalk.green(total.toString())} ${key}`; - } - return undefined; - }; - - const allChanges = allDependencyKeys.map(toLog).filter(Boolean); - const workspaceLocation = `./${path.relative( - project.paths.root, - workspace.paths.packageJson - )}`; - if (allChanges.length >= 1) { - let logLine = "updating"; - allChanges.forEach((stat, idx) => { - if (allChanges.length === 1) { - logLine += ` ${stat} in ${workspaceLocation}`; - } else { - if (idx === allChanges.length - 1) { - logLine += `and ${stat} in ${workspaceLocation}`; - } else { - logLine += ` ${stat}, `; - } - } - }); - - logger.workspaceStep(logLine); - } else { - logger.workspaceStep( - `no workspace dependencies found in ${workspaceLocation}` - ); - } - - if (!options?.dry) { - fs.writeJSONSync(workspace.paths.packageJson, workspacePackageJson, { - spaces: 2, - }); - } -} diff --git a/packages/turbo-workspaces/src/utils.ts b/packages/turbo-workspaces/src/utils.ts deleted file mode 100644 index 8290203..0000000 --- a/packages/turbo-workspaces/src/utils.ts +++ /dev/null @@ -1,197 +0,0 @@ -import fs from "fs-extra"; -import path from "path"; -import glob from "fast-glob"; -import yaml from "js-yaml"; -import { - PackageJson, - PackageManager, - Project, - Workspace, - WorkspaceInfo, -} from "./types"; -import { ConvertError } from "./errors"; - -// adapted from https://github.com/nodejs/corepack/blob/cae770694e62f15fed33dd8023649d77d96023c1/sources/specUtils.ts#L14 -const PACKAGE_MANAGER_REGEX = /^(?!_)(.+)@(.+)$/; - -function getPackageJson({ - workspaceRoot, -}: { - workspaceRoot: string; -}): PackageJson { - const packageJsonPath = path.join(workspaceRoot, "package.json"); - try { - return fs.readJsonSync(packageJsonPath, "utf8"); - } catch (err) { - if (err && typeof err === "object" && "code" in err) { - if (err.code === "ENOENT") { - throw new ConvertError(`no "package.json" found at ${workspaceRoot}`, { - type: "package_json-missing", - }); - } - if (err.code === "EJSONPARSE") { - throw new ConvertError( - `failed to parse "package.json" at ${workspaceRoot}`, - { - type: "package_json-parse_error", - } - ); - } - } - throw new Error( - `unexpected error reading "package.json" at ${workspaceRoot}` - ); - } -} - -function getWorkspacePackageManager({ - workspaceRoot, -}: { - workspaceRoot: string; -}): string | undefined { - const { packageManager } = getPackageJson({ workspaceRoot }); - if (packageManager) { - try { - const match = packageManager.match(PACKAGE_MANAGER_REGEX); - if (match) { - const [_, manager] = match; - return manager; - } - } catch (err) { - // this won't always exist. - } - } - return undefined; -} - -function getWorkspaceInfo({ - workspaceRoot, -}: { - workspaceRoot: string; -}): WorkspaceInfo { - const packageJson = getPackageJson({ workspaceRoot }); - const workspaceDirectory = path.basename(workspaceRoot); - - const { name = workspaceDirectory, description } = packageJson; - - return { - name, - description, - }; -} - -function getPnpmWorkspaces({ - workspaceRoot, -}: { - workspaceRoot: string; -}): Array<string> { - const workspaceFile = path.join(workspaceRoot, "pnpm-workspace.yaml"); - if (fs.existsSync(workspaceFile)) { - try { - const workspaceConfig = yaml.load(fs.readFileSync(workspaceFile, "utf8")); - // validate it's the type we expect - if ( - workspaceConfig instanceof Object && - "packages" in workspaceConfig && - Array.isArray(workspaceConfig.packages) - ) { - return workspaceConfig.packages as Array<string>; - } - } catch (err) { - throw new ConvertError(`failed to parse ${workspaceFile}`, { - type: "pnpm-workspace_parse_error", - }); - } - } - - return []; -} - -function expandPaths({ - root, - lockFile, - workspaceConfig, -}: { - root: string; - lockFile: string; - workspaceConfig?: string; -}) { - const fromRoot = (p: string) => path.join(root, p); - const paths: Project["paths"] = { - root, - lockfile: fromRoot(lockFile), - packageJson: fromRoot("package.json"), - nodeModules: fromRoot("node_modules"), - }; - - if (workspaceConfig) { - paths.workspaceConfig = fromRoot(workspaceConfig); - } - - return paths; -} - -function expandWorkspaces({ - workspaceRoot, - workspaceGlobs, -}: { - workspaceRoot: string; - workspaceGlobs?: string[]; -}): Array<Workspace> { - if (!workspaceGlobs) { - return []; - } - return workspaceGlobs - .flatMap((workspaceGlob) => { - const workspacePackageJsonGlob = `${workspaceGlob}/package.json`; - return glob.sync(workspacePackageJsonGlob, { - onlyFiles: true, - absolute: true, - cwd: workspaceRoot, - }); - }) - .map((workspacePackageJson) => { - const workspaceRoot = path.dirname(workspacePackageJson); - const { name, description } = getWorkspaceInfo({ workspaceRoot }); - return { - name, - description, - paths: { - root: workspaceRoot, - packageJson: workspacePackageJson, - nodeModules: path.join(workspaceRoot, "node_modules"), - }, - }; - }); -} - -function directoryInfo({ directory }: { directory: string }) { - const dir = path.resolve(process.cwd(), directory); - return { exists: fs.existsSync(dir), absolute: dir }; -} - -function getMainStep({ - packageManager, - action, - project, -}: { - packageManager: PackageManager; - action: "create" | "remove"; - project: Project; -}) { - const hasWorkspaces = project.workspaceData.globs.length > 0; - return `${action === "remove" ? "Removing" : "Adding"} ${packageManager} ${ - hasWorkspaces ? "workspaces" : "" - } ${action === "remove" ? "from" : "to"} ${project.name}`; -} - -export { - getPackageJson, - getWorkspacePackageManager, - getWorkspaceInfo, - expandPaths, - expandWorkspaces, - getPnpmWorkspaces, - directoryInfo, - getMainStep, -}; |
