Programmatic API for publishing and unpublishing npm packages with provenance support
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Functionality for removing packages or specific versions from npm registries with proper dist-tag management and tarball cleanup.
Removes packages or specific versions from the npm registry with intelligent handling of dist-tags and version management.
/**
* Unpublishes a package or specific version from the registry
* @param spec - Package specification (name, name@version, or npm-package-arg parsed object)
* @param opts - Configuration options extending npm-registry-fetch options
* @returns Promise resolving to boolean (true on success)
*/
function unpublish(spec: string | Object, opts?: UnpublishOptions): Promise<boolean>;
interface UnpublishOptions {
/** Force unpublish operation (default: false) */
force?: boolean;
/** Authentication token for registry */
token?: string;
/** Registry URL */
registry?: string;
}Usage Examples:
const { unpublish } = require('libnpmpublish');
// Unpublish entire package (all versions)
await unpublish('my-package', {
token: 'npm_1234567890abcdef'
});
// Unpublish specific version
await unpublish('my-package@1.0.0', {
token: 'npm_1234567890abcdef'
});
// Unpublish all versions using wildcard
await unpublish('my-package@*', {
token: 'npm_1234567890abcdef'
});
// Unpublish scoped package
await unpublish('@myorg/my-package@2.1.0', {
token: 'npm_1234567890abcdef'
});
// Force unpublish with explicit force flag
await unpublish('my-package', {
token: 'npm_1234567890abcdef',
force: true
});Accepts various formats for specifying what to unpublish.
/** Package specification types */
type PackageSpec = string | ParsedSpec;
interface ParsedSpec {
name: string;
rawSpec?: string;
scope?: string;
escapedName: string;
}Supported Formats:
'lodash' - Unpublishes all versions'lodash@4.17.21' - Unpublishes specific version'lodash@*' - Unpublishes all versions'@babel/core@7.0.0' - Unpublishes specific version of scoped package// Different specification formats
await unpublish('package-name'); // All versions
await unpublish('package-name@1.0.0'); // Specific version
await unpublish('package-name@*'); // All versions (explicit)
await unpublish('@scope/package@2.0.0'); // Scoped package version
// Using parsed specification
const npa = require('npm-package-arg');
const spec = npa('package-name@1.0.0');
await unpublish(spec, opts);The function exhibits different behavior based on the specification provided:
When no version is specified or * is used, removes the entire package:
// These all remove the entire package
await unpublish('my-package');
await unpublish('my-package@*');When a specific version is provided, removes only that version:
// Remove only version 1.0.0
await unpublish('my-package@1.0.0');Automatically manages dist-tags when removing specific versions:
interface DistTagBehavior {
/** Removes all dist-tags pointing to the unpublished version */
tagCleanup: boolean;
/** Recalculates 'latest' tag to point to highest remaining version */
latestRecalculation: boolean;
}Example Behavior:
// Before: my-package has versions 1.0.0, 1.1.0, 2.0.0
// Dist-tags: { latest: "2.0.0", stable: "1.1.0", beta: "2.0.0" }
await unpublish('my-package@2.0.0');
// After: my-package has versions 1.0.0, 1.1.0
// Dist-tags: { latest: "1.1.0", stable: "1.1.0" }
// (beta tag removed, latest recalculated)Works with npm-registry-fetch for all HTTP operations:
// Custom registry
await unpublish('my-package', {
registry: 'https://my-private-registry.com/',
token: 'private_registry_token'
});
// With additional npm-registry-fetch options
await unpublish('my-package', {
token: 'npm_token',
timeout: 30000,
retry: {
retries: 2,
factor: 2
}
});Returns true on successful unpublish, handles common error conditions gracefully:
Returns true when attempting to unpublish non-existent packages or versions:
// Returns true even if package doesn't exist
const result = await unpublish('non-existent-package');
console.log(result); // true
// Returns true if specific version doesn't exist
const result2 = await unpublish('existing-package@999.0.0');
console.log(result2); // trueReturns true when attempting to unpublish already-removed versions:
await unpublish('my-package@1.0.0'); // First call removes it
const result = await unpublish('my-package@1.0.0'); // Second call returns truePropagates authentication and permission errors:
try {
await unpublish('my-package', {
token: 'invalid-token'
});
} catch (error) {
// Handle authentication/authorization errors
console.error('Unpublish failed:', error.message);
}When unpublishing the only version of a package:
// If my-package only has version 1.0.0
await unpublish('my-package@1.0.0');
// Effectively removes the entire packageHandles packages with no versions gracefully:
// Returns true for packages with no versions
await unpublish('empty-package@1.0.0'); // trueWhen removing the last remaining version:
// Package with only version 2.0.0
await unpublish('my-package@2.0.0');
// Package is completely removed from registryAll unpublish operations require appropriate authentication:
await unpublish('my-package', {
token: 'npm_1234567890abcdef', // Required
registry: 'https://registry.npmjs.org/'
});