CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-libnpmpublish

Programmatic API for publishing and unpublishing npm packages with provenance support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

unpublishing.mddocs/

Package Unpublishing

Functionality for removing packages or specific versions from npm registries with proper dist-tag management and tarball cleanup.

Capabilities

Unpublish Function

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

Package Specification Formats

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:

  • Package name only: 'lodash' - Unpublishes all versions
  • Package with version: 'lodash@4.17.21' - Unpublishes specific version
  • Package with wildcard: 'lodash@*' - Unpublishes all versions
  • Scoped package: '@babel/core@7.0.0' - Unpublishes specific version of scoped package
  • Parsed object: Pre-parsed npm-package-arg object
// 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);

Unpublish Behavior

The function exhibits different behavior based on the specification provided:

Complete Package Removal

When no version is specified or * is used, removes the entire package:

  • Deletes all package versions
  • Removes all dist-tags
  • Deletes package metadata
  • Removes all associated tarballs
// These all remove the entire package
await unpublish('my-package');
await unpublish('my-package@*');

Specific Version Removal

When a specific version is provided, removes only that version:

  • Deletes the specified version from the versions object
  • Updates dist-tags that pointed to the removed version
  • Recalculates the 'latest' tag if it pointed to the removed version
  • Removes the associated tarball file
// Remove only version 1.0.0
await unpublish('my-package@1.0.0');

Dist-Tag Management

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)

Registry Integration

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

Error Handling

Returns true on successful unpublish, handles common error conditions gracefully:

Package Not Found (E404)

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); // true

Version Already Removed

Returns 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 true

Authentication Errors

Propagates authentication and permission errors:

try {
  await unpublish('my-package', {
    token: 'invalid-token'
  });
} catch (error) {
  // Handle authentication/authorization errors
  console.error('Unpublish failed:', error.message);
}

Edge Cases

Single Version Package

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 package

Empty Package State

Handles packages with no versions gracefully:

// Returns true for packages with no versions
await unpublish('empty-package@1.0.0');  // true

Last Version Removal

When removing the last remaining version:

// Package with only version 2.0.0
await unpublish('my-package@2.0.0');
// Package is completely removed from registry

Authentication Requirements

All unpublish operations require appropriate authentication:

  • Package owner: Can unpublish any version
  • Organization member: Can unpublish organization packages (with permissions)
  • Registry admin: Can unpublish any package (registry-dependent)
await unpublish('my-package', {
  token: 'npm_1234567890abcdef',  // Required
  registry: 'https://registry.npmjs.org/'
});

docs

index.md

publishing.md

unpublishing.md

tile.json