mirror of
https://github.com/warkanum/monorepo-dep-checker.git
synced 2025-05-18 18:57:29 +00:00
Added linting, changed to esm loading
This commit is contained in:
parent
78e54af042
commit
44ff9878dd
152
README.md
152
README.md
@ -1,2 +1,152 @@
|
|||||||
# monorepo-dep-checker
|
# 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
|
@ -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);
|
||||||
|
9
eslint.config.js
Normal file
9
eslint.config.js
Normal file
@ -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,
|
||||||
|
];
|
@ -42,7 +42,9 @@
|
|||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.55.0",
|
"@eslint/js": "^9.15.0",
|
||||||
|
"eslint": "^8.57.1",
|
||||||
|
"globals": "^15.12.0",
|
||||||
"vite": "^5.0.0",
|
"vite": "^5.0.0",
|
||||||
"vitest": "^1.0.0"
|
"vitest": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
11
src/index.js
11
src/index.js
@ -1,6 +1,5 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import yargs from 'yargs';
|
import yargs from 'yargs';
|
||||||
@ -132,6 +131,7 @@ class DependencyChecker {
|
|||||||
|
|
||||||
if (missing.length > 0 || extraDeps.length > 0) {
|
if (missing.length > 0 || extraDeps.length > 0) {
|
||||||
missingDeps.set(packageName, {
|
missingDeps.set(packageName, {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
path: path.relative(process.cwd(), filePath),
|
path: path.relative(process.cwd(), filePath),
|
||||||
missing,
|
missing,
|
||||||
extraDeps,
|
extraDeps,
|
||||||
@ -277,6 +277,7 @@ class DependencyChecker {
|
|||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
package: pkg,
|
package: pkg,
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
path: path.relative(process.cwd(), filePath),
|
path: path.relative(process.cwd(), filePath),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
@ -410,6 +411,7 @@ class DependencyChecker {
|
|||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
package: pkg,
|
package: pkg,
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
path: path.relative(process.cwd(), filePath),
|
path: path.relative(process.cwd(), filePath),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
@ -571,6 +573,7 @@ class DependencyChecker {
|
|||||||
|
|
||||||
// CLI implementation
|
// CLI implementation
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
const argv = yargs(hideBin(process.argv))
|
const argv = yargs(hideBin(process.argv))
|
||||||
.usage('Usage: $0 [options]')
|
.usage('Usage: $0 [options]')
|
||||||
.option('app', {
|
.option('app', {
|
||||||
@ -621,17 +624,21 @@ const run = async () => {
|
|||||||
.example('$0 --check-missing', 'Show missing dependencies')
|
.example('$0 --check-missing', 'Show missing dependencies')
|
||||||
.example('$0 --update --dry-run', 'Show what would be updated').argv;
|
.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);
|
const appPackageJson = path.resolve(process.cwd(), argv.app);
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
const packagesDir = path.resolve(process.cwd(), argv.packages);
|
const packagesDir = path.resolve(process.cwd(), argv.packages);
|
||||||
|
|
||||||
// Validate paths
|
// Validate paths
|
||||||
if (!fs.existsSync(appPackageJson)) {
|
if (!fs.existsSync(appPackageJson)) {
|
||||||
console.error(chalk.red(`Error: Main package.json not found at ${appPackageJson}`));
|
console.error(chalk.red(`Error: Main package.json not found at ${appPackageJson}`));
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(packagesDir)) {
|
if (!fs.existsSync(packagesDir)) {
|
||||||
console.error(chalk.red(`Error: Packages directory not found at ${packagesDir}`));
|
console.error(chalk.red(`Error: Packages directory not found at ${packagesDir}`));
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,7 +655,7 @@ const run = async () => {
|
|||||||
// Export both the class and run function
|
// Export both the class and run function
|
||||||
export { DependencyChecker, run as default };
|
export { DependencyChecker, run as default };
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
if (process.argv[1] === import.meta.url.slice(7)) {
|
if (process.argv[1] === import.meta.url.slice(7)) {
|
||||||
console.log('Running');
|
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user