|
|
|
|
@@ -115,7 +115,7 @@ class PackageManager {
|
|
|
|
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
|
|
|
const dependencies = {
|
|
|
|
|
...packageJson.dependencies,
|
|
|
|
|
...(options.includeDev ? packageJson.devDependencies : {})
|
|
|
|
|
...(options.includeDev || options.saveDev ? packageJson.devDependencies : {})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (Object.keys(dependencies).length === 0) {
|
|
|
|
|
@@ -348,10 +348,14 @@ class PackageManager {
|
|
|
|
|
...packageJson.dependencies,
|
|
|
|
|
...(options.includeDev ? packageJson.devDependencies : {})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const optionalDependencies = packageJson.optionalDependencies || {};
|
|
|
|
|
|
|
|
|
|
if (!dependencies || Object.keys(dependencies).length === 0) {
|
|
|
|
|
// No dependencies to install
|
|
|
|
|
return;
|
|
|
|
|
// If no regular dependencies, check if there are optional dependencies to install
|
|
|
|
|
if (Object.keys(optionalDependencies).length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize installed packages tracking if not exists
|
|
|
|
|
@@ -368,6 +372,14 @@ class PackageManager {
|
|
|
|
|
|
|
|
|
|
console.log(chalk.blue(`Installing dependencies for ${packageName}...`));
|
|
|
|
|
|
|
|
|
|
// Install dependencies recursively by calling installPackages
|
|
|
|
|
const depOptions = {
|
|
|
|
|
...options,
|
|
|
|
|
fromPackageJson: true, // Prevent updating package.json
|
|
|
|
|
_depth: currentDepth + 1, // Increment depth
|
|
|
|
|
_installedPackages: options._installedPackages // Pass along installed packages set
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Filter out already installed packages to avoid duplicates
|
|
|
|
|
const dependenciesToInstall = Object.entries(dependencies).filter(([name, version]) => {
|
|
|
|
|
const packageKey = `${name}@${version}`;
|
|
|
|
|
@@ -384,37 +396,74 @@ class PackageManager {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (dependenciesToInstall.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
// No regular dependencies to install, but continue to check optional dependencies
|
|
|
|
|
} else {
|
|
|
|
|
// Prepare dependency specs for installation
|
|
|
|
|
const dependencySpecs = dependenciesToInstall.map(([name, version]) => {
|
|
|
|
|
// Mark as installed to prevent duplicates
|
|
|
|
|
options._installedPackages.add(`${name}@${version}`);
|
|
|
|
|
|
|
|
|
|
// Handle various version formats
|
|
|
|
|
if (version.startsWith('^') || version.startsWith('~') || version.startsWith('>=') || version.startsWith('<=')) {
|
|
|
|
|
return `${name}@${version}`;
|
|
|
|
|
} else if (version === '*' || version === 'latest') {
|
|
|
|
|
return `${name}@latest`;
|
|
|
|
|
} else if (semver.validRange(version)) {
|
|
|
|
|
return `${name}@${version}`;
|
|
|
|
|
} else {
|
|
|
|
|
// For non-semver versions (git urls, file paths, etc.), use as-is
|
|
|
|
|
return `${name}@${version}`;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Install dependencies
|
|
|
|
|
await this.installPackages(dependencySpecs, depOptions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prepare dependency specs for installation
|
|
|
|
|
const dependencySpecs = dependenciesToInstall.map(([name, version]) => {
|
|
|
|
|
// Mark as installed to prevent duplicates
|
|
|
|
|
options._installedPackages.add(`${name}@${version}`);
|
|
|
|
|
|
|
|
|
|
// Handle various version formats
|
|
|
|
|
if (version.startsWith('^') || version.startsWith('~') || version.startsWith('>=') || version.startsWith('<=')) {
|
|
|
|
|
return `${name}@${version}`;
|
|
|
|
|
} else if (version === '*' || version === 'latest') {
|
|
|
|
|
return `${name}@latest`;
|
|
|
|
|
} else if (semver.validRange(version)) {
|
|
|
|
|
return `${name}@${version}`;
|
|
|
|
|
} else {
|
|
|
|
|
// For non-semver versions (git urls, file paths, etc.), use as-is
|
|
|
|
|
return `${name}@${version}`;
|
|
|
|
|
// Install optional dependencies (ignore failures)
|
|
|
|
|
if (Object.keys(optionalDependencies).length > 0) {
|
|
|
|
|
const optionalDependenciesToInstall = Object.entries(optionalDependencies).filter(([name, version]) => {
|
|
|
|
|
const packageKey = `${name}@${version}`;
|
|
|
|
|
if (options._installedPackages && options._installedPackages.has(packageKey)) {
|
|
|
|
|
return false; // Skip already installed package
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if package already exists in node_modules
|
|
|
|
|
const targetDir = options.global
|
|
|
|
|
? path.join(this.globalRoot, 'node_modules', name)
|
|
|
|
|
: path.join(this.projectRoot, 'node_modules', name);
|
|
|
|
|
|
|
|
|
|
const exists = fs.existsSync(targetDir);
|
|
|
|
|
return !exists;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (optionalDependenciesToInstall.length > 0) {
|
|
|
|
|
const optionalSpecs = optionalDependenciesToInstall.map(([name, version]) => {
|
|
|
|
|
// Mark as installed to prevent duplicates
|
|
|
|
|
if (options._installedPackages) {
|
|
|
|
|
options._installedPackages.add(`${name}@${version}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle various version formats
|
|
|
|
|
if (version.startsWith('^') || version.startsWith('~') || version.startsWith('>=') || version.startsWith('<=')) {
|
|
|
|
|
return `${name}@${version}`;
|
|
|
|
|
} else if (version === '*' || version === 'latest') {
|
|
|
|
|
return `${name}@latest`;
|
|
|
|
|
} else if (semver.validRange(version)) {
|
|
|
|
|
return `${name}@${version}`;
|
|
|
|
|
} else {
|
|
|
|
|
return `${name}@${version}`;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Install optional dependencies (ignore failures)
|
|
|
|
|
try {
|
|
|
|
|
await this.installPackages(optionalSpecs, depOptions);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.warn(chalk.yellow(`Some optional dependencies for ${packageName} could not be installed (this is usually safe to ignore)`));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Install dependencies recursively by calling installPackages
|
|
|
|
|
const depOptions = {
|
|
|
|
|
...options,
|
|
|
|
|
fromPackageJson: true, // Prevent updating package.json
|
|
|
|
|
_depth: currentDepth + 1, // Increment depth
|
|
|
|
|
_installedPackages: options._installedPackages // Pass along installed packages set
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Install dependencies
|
|
|
|
|
await this.installPackages(dependencySpecs, depOptions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.warn(chalk.yellow(`Failed to install dependencies for ${packageName}: ${error.message}`));
|
|
|
|
|
|