Skip to content

hyperse-io/dependency-sync

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

@hyperse/dependency-sync

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.

Features

  • 🔍 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

Installation

npm install @hyperse/dependency-sync
# or
yarn add @hyperse/dependency-sync
# or
pnpm add @hyperse/dependency-sync

Quick Start

Basic Usage

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/*',
]);

Advanced Configuration

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'],
});

API Reference

syncDependencies(workspaceRoot?, options?)

Synchronizes dependencies across all packages in the workspace.

Parameters

  • workspaceRoot (string, optional): Root directory of the workspace. Defaults to process.cwd()
  • options (SyncDependenciesOptions, optional): Configuration options

Options

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

import { syncDependencies } from '@hyperse/dependency-sync';

// Sync all packages in the current workspace
await syncDependencies();

Example 2: Custom Peer Dependencies Configuration

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'],
});

Example 3: Conflict Detection

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(', ')}`);
}

Example 4: Excluding Specific Packages

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,
});

Example 5: Integration with Build Scripts

{
  "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"
  }
}

How It Works

Dependency Synchronization Process

  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

Conflict Detection Process

  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

Configuration Best Practices

Peer Dependencies Configuration

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',
};

Dependency Relationships

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'],
};

Ignored Packages

const ignoredPackages = [
  // Build tools
  'dotenv',
  'sharp',

  // File system utilities
  'fs-capacitor',

  // Express (handled by NestJS)
  'express',
];

Troubleshooting

Common Issues

  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

Error Messages

  • 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 file for details.

Support

For support and questions, please open an issue on the GitHub repository.

About

A comprehensive Node.js utility for managing dependencies in monorepo environments, specifically designed for Hyperse plugin ecosystems.

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors