@hyperse/dependency-sync
Version:
A comprehensive Node.js utility for managing dependencies in monorepo environments, specifically designed for Hyperse plugin ecosystems.
319 lines (230 loc) • 9.16 kB
Markdown
A comprehensive Node.js utility for managing dependencies in monorepo environments, specifically designed for Hyperse plugin ecosystems. This tool helps maintain consistent dependency management across multiple packages in a workspace.
- 🔍 **Dependency Conflict Detection**: Identify and resolve version conflicts in `node_modules`
- 📦 **Peer Dependency Synchronization**: Automatically sync peer dependencies across packages
- 🚨 **Missing Package Detection**: Check for undeclared imports in source files
- 🏗️ **Monorepo Support**: Built for managing multiple packages in a single workspace
- ⚡ **TypeScript Support**: Full TypeScript support with type definitions
- 🎯 **Hyperse Ecosystem Optimized**: Specifically designed for Hyperse plugin development
```bash
npm install @hyperse/dependency-sync
yarn add @hyperse/dependency-sync
pnpm add @hyperse/dependency-sync
```
```typescript
import { syncDependencies, checkConflicts } from '@hyperse/dependency-sync';
// Sync dependencies across all packages in the workspace
await syncDependencies();
// Check for dependency conflicts
const conflicts = await checkConflicts('./node_modules', [
'@vendure/*',
'@nestjs/*',
]);
```
```typescript
import { syncDependencies } from '@hyperse/dependency-sync';
await syncDependencies(process.cwd(), {
// Exclude specific packages from processing
excludedPackages: (pkg) => pkg.packageJson.name === 'admin-ui',
// Disable missing package checks
checkMissing: false,
// Define peer dependencies and their versions
maxRangeCanbeSyncPeerDependencies: {
'@vendure/core': '^3.3.5',
'@nestjs/common': '^11.1.3',
graphql: '^16.11.0',
},
// Define dependency relationships
dependenciesReferPeepDependencies: {
'@nestjs/graphql': ['@nestjs/core'],
'@hyperse-hub/vendure-plugin-email': ['@vendure/common'],
},
// Packages to ignore during checks
ignoredCheckList: ['dotenv', 'fs-capacitor', 'sharp'],
});
```
Synchronizes dependencies across all packages in the workspace.
- `workspaceRoot` (string, optional): Root directory of the workspace. Defaults to `process.cwd()`
- `options` (SyncDependenciesOptions, optional): Configuration options
```typescript
interface SyncDependenciesOptions {
excludedPackages?: (pkg: Package) => boolean;
checkMissing?: boolean;
maxRangeCanbeSyncPeerDependencies?: Record<string, string>;
dependenciesReferPeepDependencies?: Record<string, string[]>;
ignoredCheckList?: string[];
}
```
- `excludedPackages`: Function to filter out packages from processing
- `checkMissing`: Whether to check for missing package declarations (default: `true`)
- `maxRangeCanbeSyncPeerDependencies`: Map of peer dependencies and their versions
- `dependenciesReferPeepDependencies`: Map of dependencies that reference peer dependencies
- `ignoredCheckList`: List of packages to ignore when checking for missing declarations
### `checkConflicts(nodeModulesPath, pkgPatterns, ignorePackages?)`
Checks for conflicting package versions in `node_modules`.
#### Parameters
- `nodeModulesPath` (string): Path to the `node_modules` directory
- `pkgPatterns` (string[]): Array of package patterns to check (e.g., `['@vendure/*', '@nestjs/*']`)
- `ignorePackages` (string[], optional): Packages to ignore when checking for conflicts
#### Returns
Returns a `Map<string, string[]>` where keys are package names and values are arrays of conflicting versions.
### `checkMissedPackageDeclaration(projectCwd, ignoredCheckList)`
Checks if imported packages in source files are missing from `package.json`.
#### Parameters
- `projectCwd` (string): The project directory
- `ignoredCheckList` (string[]): List of packages to ignore
### `extractImportedModules(projectCwd)`
Extracts all imported modules from the project's source files.
#### Parameters
- `projectCwd` (string): The project directory
#### Returns
Returns a `Set<string>` of imported module names.
## Examples
### Example 1: Basic Dependency Synchronization
```typescript
import { syncDependencies } from '@hyperse/dependency-sync';
// Sync all packages in the current workspace
await syncDependencies();
```
```typescript
import { syncDependencies } from '@hyperse/dependency-sync';
const peerDependencies = {
'@vendure/core': '^3.3.5',
'@vendure/common': '^3.3.5',
'@nestjs/common': '^11.1.3',
'@nestjs/core': '^11.1.3',
graphql: '^16.11.0',
typeorm: '^0.3.24',
};
const dependencyRelationships = {
'@nestjs/graphql': ['@nestjs/core'],
'@hyperse-hub/vendure-plugin-email': ['@vendure/common'],
'@hyperse-hub/vendure-testing': ['graphql'],
};
await syncDependencies(process.cwd(), {
maxRangeCanbeSyncPeerDependencies: peerDependencies,
dependenciesReferPeepDependencies: dependencyRelationships,
ignoredCheckList: ['dotenv', 'fs-capacitor', 'sharp', 'express'],
});
```
```typescript
import { checkConflicts } from '@hyperse/dependency-sync';
// Check for conflicts in Vendure and NestJS packages
const conflicts = await checkConflicts('./node_modules', [
'@vendure/*',
'@nestjs/*',
'@hyperse-hub/*',
]);
// Log conflicts
for (const [packageName, versions] of conflicts) {
console.log(`${packageName}: ${versions.join(', ')}`);
}
```
```typescript
import { syncDependencies } from '@hyperse/dependency-sync';
await syncDependencies(process.cwd(), {
excludedPackages: (pkg) => {
// Exclude admin-ui packages
return (
pkg.packageJson.name.includes('admin-ui') ||
pkg.packageJson.name.includes('dashboard')
);
},
checkMissing: true,
});
```
```json
{
"scripts": {
"sync-deps": "node -e \"import('@hyperse/dependency-sync').then(m => m.syncDependencies())\"",
"check-conflicts": "node -e \"import('@hyperse/dependency-sync').then(m => m.checkConflicts('./node_modules', ['@vendure/*', '@nestjs/*']).then(console.log))\"",
"prebuild": "yarn sync-deps"
}
}
```
1. **Package Discovery**: Scans the workspace for all packages using `@manypkg/get-packages`
2. **Import Analysis**: Extracts all imported modules from source files
3. **Peer Dependency Resolution**: Identifies which imports should be peer dependencies
4. **Dependency Reorganization**: Moves peer dependencies to `peerDependencies` and regular dependencies to `devDependencies`
5. **Package.json Updates**: Updates all package.json files with the new dependency structure
1. **Pattern Matching**: Searches for packages matching the provided patterns
2. **Version Collection**: Collects all versions of each package found
3. **Conflict Identification**: Identifies packages with multiple versions
4. **Filtering**: Removes ignored packages from the results
```typescript
const peerDependencies = {
// Core framework dependencies
'@vendure/core': '^3.3.5',
'@vendure/common': '^3.3.5',
// NestJS dependencies
'@nestjs/common': '^11.1.3',
'@nestjs/core': '^11.1.3',
// GraphQL dependencies
graphql: '^16.11.0',
'@apollo/server': '^4.12.2',
// Database dependencies
typeorm: '^0.3.24',
};
```
```typescript
const relationships = {
// NestJS modules that depend on core
'@nestjs/graphql': ['@nestjs/core'],
'@nestjs/apollo': ['@nestjs/core'],
// Hyperse plugins that depend on Vendure
'@hyperse-hub/vendure-plugin-email': ['@vendure/common'],
'@hyperse-hub/vendure-plugin-payment-core': ['@nestjs/graphql'],
};
```
```typescript
const ignoredPackages = [
// Build tools
'dotenv',
'sharp',
// File system utilities
'fs-capacitor',
// Express (handled by NestJS)
'express',
];
```
1. **Missing Package Declarations**: Ensure all imported packages are declared in `package.json`
2. **Version Conflicts**: Use `checkConflicts` to identify and resolve version conflicts
3. **Peer Dependency Issues**: Verify that peer dependencies are correctly configured
- `No declared package (packageName) in projectPath!`: A package is imported but not declared in `package.json`
- `referPeerDependency packageName not found in maxRangeCanbeSyncPeerDependencies`: A dependency relationship references an undefined peer dependency
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Run the test suite
6. Submit a pull request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Support
For support and questions, please open an issue on the [GitHub repository](https://github.com/hyperse-io/dependency-sync).