diff --git a/README.md b/README.md index c86c407..6f2fb7f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,152 @@ # monorepo-dep-checker -A CLI tool to check and manage dependencies across packages in a monorepo + +A powerful CLI tool for managing and checking dependencies across packages in a monorepo. Helps you identify version mismatches, missing dependencies, and maintain consistency across your workspace packages. + +## Features + +- 🔍 Check for version differences across packages +- ⚠️ Identify missing dependencies between your main app and packages +- 🔄 Update dependencies to the highest compatible version +- 🏗️ Full workspace package support +- 📊 Clear, actionable summaries +- 🚀 Fast, zero-config setup + +## Installation + +```bash +# Global installation +npm install -g @warkypublic/monorepo-dep-checker + +# Or locally in your project +npm install --save-dev @warkypublic/monorepo-dep-checker +``` + +## Quick Start + +Basic usage with default paths (assumes `./package.json` for main app and `./packages` for workspace packages): + +```bash +dep-check +``` + +## Usage Examples + +### 1. Check Version Differences + +Find packages using different versions of the same dependency: + +```bash +dep-check --check-versions + +# Output example: +react: + Difference (major): + ^17.0.2 vs ^18.0.0 + + Packages using ^17.0.2: + - my-app (package.json) + - components (packages/components/package.json) + + Packages using ^18.0.0: + - new-feature (packages/new-feature/package.json) + + Recommended action: + ⚠️ Major version difference - Manual review recommended +``` + +### 2. Check Missing Dependencies + +Find dependencies that exist in packages but are missing from the main app: + +```bash +dep-check --check-missing + +# Output example: +Summary: +Packages with dependency mismatches: 2 +Unique dependencies missing from main app: 1 + lodash +Unique unused dependencies from main app: 1 + axios +``` + +### 3. Update Dependencies + +Update all dependencies to their highest compatible version: + +```bash +# Dry run - show what would be updated +dep-check --update --dry-run + +# Actually perform the updates +dep-check --update +``` + +### 4. Custom Paths + +Specify custom paths for your main app and packages: + +```bash +dep-check --app ../my-app/package.json --packages ../my-app/packages +``` + +### 5. JSON Output + +Get results in JSON format for further processing: + +```bash +dep-check --check-versions --format json +``` + +## Command Line Options + +```bash +Options: + --app, -a Path to main app package.json [default: "./package.json"] + --packages, -p Path to packages directory [default: "./packages"] + --update, -u Update dependencies to highest compatible version + --dry-run, -d Show what would be updated without making changes + --check-versions Check for version differences between packages + --check-missing Check for dependencies missing between app and packages + --format Output format (text or json) [default: "text"] + --help Show help + --version Show version number +``` + +## Features + +### Workspace Support + +- Automatically detects and handles workspace dependencies +- Ignores `workspace:*` protocol dependencies +- Properly manages workspace package references +- Supports npm, yarn, and pnpm workspaces + +### Version Analysis + +- Identifies major, minor, and patch version differences +- Provides clear upgrade recommendations +- Shows detailed package locations +- Helps prevent dependency conflicts + +### Missing Dependency Detection + +- Finds dependencies used in packages but missing from main app +- Identifies unused main app dependencies +- Shows unique missing dependencies to avoid duplication +- Excludes workspace packages from analysis + +## Best Practices + +1. Run `--check-versions` before updates to identify potential breaking changes +2. Use `--dry-run` before applying updates +3. Review major version differences manually +4. Keep workspace dependencies consistent across packages + +## Contributing + +Contributions are welcome! Please read our contributing guidelines for details. + +## License + +MIT License - see LICENSE file for details \ No newline at end of file diff --git a/bin/dep-check.js b/bin/dep-check.js index 024383f..a2ca9bb 100644 --- a/bin/dep-check.js +++ b/bin/dep-check.js @@ -1 +1,12 @@ -import('../dist/index.js').then(module => module.default()).catch(console.error); +#!/usr/bin/env node + +import { createRequire } from 'module'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const require = createRequire(import.meta.url); + +const { default: run } = await import(join(__dirname, '../dist/index.js')); +run().catch(console.error); diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..6d1eeba --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,9 @@ +import globals from "globals"; +import pluginJs from "@eslint/js"; + + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + {languageOptions: { globals: globals.browser }}, + pluginJs.configs.recommended, +]; \ No newline at end of file diff --git a/package.json b/package.json index e57ec38..6a89725 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,9 @@ "yargs": "^17.7.2" }, "devDependencies": { - "eslint": "^8.55.0", + "@eslint/js": "^9.15.0", + "eslint": "^8.57.1", + "globals": "^15.12.0", "vite": "^5.0.0", "vitest": "^1.0.0" }, diff --git a/src/index.js b/src/index.js index 3b77ce3..a659c1d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,5 @@ import fs from 'fs'; import path from 'path'; -import { fileURLToPath } from 'url'; import chalk from 'chalk'; import semver from 'semver'; import yargs from 'yargs'; @@ -132,6 +131,7 @@ class DependencyChecker { if (missing.length > 0 || extraDeps.length > 0) { missingDeps.set(packageName, { + // eslint-disable-next-line no-undef path: path.relative(process.cwd(), filePath), missing, extraDeps, @@ -277,6 +277,7 @@ class DependencyChecker { }); return { package: pkg, + // eslint-disable-next-line no-undef path: path.relative(process.cwd(), filePath), }; }), @@ -410,6 +411,7 @@ class DependencyChecker { }); return { package: pkg, + // eslint-disable-next-line no-undef path: path.relative(process.cwd(), filePath), }; }), @@ -571,6 +573,7 @@ class DependencyChecker { // CLI implementation const run = async () => { + // eslint-disable-next-line no-undef const argv = yargs(hideBin(process.argv)) .usage('Usage: $0 [options]') .option('app', { @@ -621,17 +624,21 @@ const run = async () => { .example('$0 --check-missing', 'Show missing dependencies') .example('$0 --update --dry-run', 'Show what would be updated').argv; + // eslint-disable-next-line no-undef const appPackageJson = path.resolve(process.cwd(), argv.app); + // eslint-disable-next-line no-undef const packagesDir = path.resolve(process.cwd(), argv.packages); // Validate paths if (!fs.existsSync(appPackageJson)) { console.error(chalk.red(`Error: Main package.json not found at ${appPackageJson}`)); + // eslint-disable-next-line no-undef process.exit(1); } if (!fs.existsSync(packagesDir)) { console.error(chalk.red(`Error: Packages directory not found at ${packagesDir}`)); + // eslint-disable-next-line no-undef process.exit(1); } @@ -648,7 +655,7 @@ const run = async () => { // Export both the class and run function export { DependencyChecker, run as default }; +// eslint-disable-next-line no-undef if (process.argv[1] === import.meta.url.slice(7)) { - console.log('Running'); run(); }