local-npm-registry
Version:
Manages local npm package installations and updates across your machine.
146 lines (126 loc) • 5.03 kB
text/typescript
import { DR } from '@aneuhold/core-ts-lib';
import { LocalPackageStoreService } from '../services/LocalPackageStoreService.js';
import { PackageJsonService } from '../services/PackageJsonService.js';
import { PackageManagerService } from '../services/PackageManagerService/PackageManagerService.js';
/**
* Implements the 'local-npm unsubscribe [<package-name>]' command.
*/
export class UnsubscribeCommand {
/**
* Implements the 'local-npm unsubscribe [<package-name>]' command.
*
* @param packageName - Optional package name to unsubscribe from. If not provided, unsubscribes from all packages
*/
static async execute(packageName?: string): Promise<void> {
const currentProjectPath = process.cwd();
if (packageName) {
// Unsubscribe from specific package
await this.unsubscribeFromSpecificPackage(packageName, currentProjectPath);
} else {
// Unsubscribe from all packages
await this.unsubscribeFromAllPackages(currentProjectPath);
}
}
/**
* Unsubscribes from a specific package.
*
* @param packageName - Name of the package to unsubscribe from
* @param currentProjectPath - Path to the current project
*/
private static async unsubscribeFromSpecificPackage(
packageName: string,
currentProjectPath: string
): Promise<void> {
const entry = await LocalPackageStoreService.getPackageEntry(packageName);
if (!entry) {
throw new Error(`Package '${packageName}' not found in local registry`);
}
const subscriber = entry.subscribers.find((sub) => sub.subscriberPath === currentProjectPath);
if (!subscriber) {
throw new Error(`Subscriber data not found for ${packageName}`);
}
// Remove current project from subscribers list
await LocalPackageStoreService.removeSubscriber(packageName, currentProjectPath);
// Reset to original version
await PackageJsonService.updatePackageVersion(
currentProjectPath,
packageName,
subscriber.originalSpecifier
);
try {
await PackageManagerService.runInstall(currentProjectPath);
} catch (error) {
DR.logger.warn(
`Install failed after unsubscribing from ${packageName}: ${String(error)}. The package.json has been reset successfully.`
);
}
DR.logger.info(`Successfully unsubscribed from ${packageName}`);
}
/**
* Unsubscribes from all packages.
*
* @param currentProjectPath - Path to the current project
*/
private static async unsubscribeFromAllPackages(currentProjectPath: string): Promise<void> {
const subscribedPackages =
await LocalPackageStoreService.getSubscribedPackages(currentProjectPath);
if (subscribedPackages.length === 0) {
DR.logger.info('No packages to unsubscribe from');
return;
}
DR.logger.info(`Unsubscribing from ${subscribedPackages.length} package(s)`);
// Perform unsubscribe operations in parallel
const unsubscribePromises = subscribedPackages.map(async (pkgName) => {
try {
const entry = await LocalPackageStoreService.getPackageEntry(pkgName);
if (entry) {
// Find the subscriber to get their original specifier
const subscriber = entry.subscribers.find(
(sub) => sub.subscriberPath === currentProjectPath
);
if (!subscriber) {
return {
packageName: pkgName,
success: false,
error: 'Subscriber data not found'
};
}
// Remove current project from subscribers list
await LocalPackageStoreService.removeSubscriber(pkgName, currentProjectPath);
// Reset to original version using subscriber's original specifier
await PackageJsonService.updatePackageVersion(
currentProjectPath,
pkgName,
subscriber.originalSpecifier
);
return { packageName: pkgName, success: true };
}
return {
packageName: pkgName,
success: false,
error: 'Entry not found'
};
} catch (error) {
DR.logger.error(`Failed to unsubscribe from ${pkgName}: ${String(error)}`);
return { packageName: pkgName, success: false, error };
}
});
// Wait for all unsubscribe operations to complete
const results = await Promise.allSettled(unsubscribePromises);
const successCount = results.filter(
(result) => result.status === 'fulfilled' && result.value.success
).length;
DR.logger.info(
`Parallel unsubscribe completed: ${successCount}/${subscribedPackages.length} successful`
);
// Run install once after all updates
try {
await PackageManagerService.runInstall(currentProjectPath);
} catch (error) {
DR.logger.warn(
`Install failed after unsubscribing from all packages: ${String(error)}. The package.json files have been reset successfully.`
);
}
DR.logger.info(`Successfully unsubscribed from all packages`);
}
}