CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-changesets--cli

Organise your package versioning and publishing to make both contributors and maintainers happy

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

publishing.mddocs/

Package Publishing

Package publishing automates the process of releasing packages to npm registries with support for 2FA, custom tags, git tagging, and multi-package coordination.

Capabilities

Main Publishing Function

The primary function for publishing packages to npm and creating git tags.

/**
 * Publishes packages to npm registry and creates git tags
 * @param cwd - Working directory path
 * @param options.otp - One-time password for 2FA authentication
 * @param options.tag - Custom npm dist-tag (defaults to "latest")
 * @param options.gitTag - Whether to create git tags (defaults to true)
 * @param config - Changesets configuration object
 */
function publish(
  cwd: string, 
  options: {otp?: string, tag?: string, gitTag?: boolean}, 
  config: Config
): Promise<void>;

Usage Examples:

import { run } from "@changesets/cli";

// Standard publishing
await run(["publish"], {}, cwd);

// Publishing with 2FA token
await run(["publish"], { otp: "123456" }, cwd);

// Publishing with custom tag
await run(["publish"], { tag: "beta" }, cwd);

// Publishing without git tags
await run(["publish"], { gitTag: false }, cwd);

Core Package Publishing

Lower-level function for publishing individual packages with detailed control.

/**
 * Core package publishing logic for multiple packages
 * @param options.packages - Array of packages to publish
 * @param options.access - Package access level (public or restricted)
 * @param options.otp - One-time password for 2FA
 * @param options.preState - Prerelease state for coordinated prereleases
 * @param options.tag - Custom npm dist-tag
 * @returns Array of publish results with success/failure status
 */
function publishPackages(options: {
  packages: Package[], 
  access: AccessType, 
  otp?: string, 
  preState: PreState | undefined, 
  tag?: string
}): Promise<PublishedResult[]>;

Usage Examples:

import publishPackages from "@changesets/cli/src/commands/publish/publishPackages";

const results = await publishPackages({
  packages: packagesToPublish,
  access: "public",
  otp: process.env.NPM_OTP,
  preState: undefined,
  tag: "latest"
});

// Check results
results.forEach(result => {
  if (result.published) {
    console.log(`✓ Published ${result.name}@${result.newVersion}`);
  } else {
    console.log(`✗ Failed to publish ${result.name}`);
  }
});

NPM Registry Integration

Registry Detection and Configuration

Utilities for handling npm registry configuration and authentication.

/**
 * Determines the correct npm registry for a package
 * @param packageJson - Package.json object (optional)
 * @returns Registry information including scope and URL
 */
function getCorrectRegistry(packageJson?: PackageJSON): RegistryInfo;

/**
 * Checks if 2FA token is required for publishing
 * @returns Promise resolving to boolean indicating 2FA requirement
 */
function getTokenIsRequired(): Promise<boolean>;

/**
 * Gets package information from npm registry
 * @param packageJson - Package.json object
 * @returns Promise resolving to package registry information
 */
function getPackageInfo(packageJson: PackageJSON): Promise<any>;

/**
 * Gets package info from registry, handling 404s gracefully
 * @param packageJson - Package.json object  
 * @returns Promise resolving to publish status and package info
 */
function infoAllow404(
  packageJson: PackageJSON
): Promise<{published: boolean, pkgInfo: any}>;

Two-Factor Authentication

Comprehensive 2FA support for secure publishing:

/**
 * Gets 2FA token from user input or existing state
 * @param twoFactorState - Current 2FA state object
 * @returns Promise resolving to OTP token string
 */
function getOtpCode(twoFactorState: TwoFactorState): Promise<string>;

/**
 * Publishes a single package to npm with 2FA support
 * @param packageJson - Package.json object
 * @param opts - Publishing options including registry and access
 * @param twoFactorState - 2FA state for token management
 * @returns Promise resolving to publish result
 */
function publish(
  packageJson: PackageJSON, 
  opts: PublishOptions, 
  twoFactorState: TwoFactorState
): Promise<{published: boolean}>;

2FA State Management:

interface TwoFactorState {
  token: string | null;
  isRequired: Promise<boolean>;
}

Git Tag Management

Automatic Git Tagging

Publishing automatically creates git tags for published versions:

// Default tag format: {packageName}@{version}
// Examples:
// @myorg/ui@1.2.0
// my-package@2.1.0

Manual Tag Creation

Separate tag creation for packages that were published externally:

/**
 * Creates git tags for published packages
 * @param cwd - Working directory path
 * @param config - Changesets configuration object
 */
function tag(cwd: string, config: Config): Promise<void>;

Untagged Package Detection

Utility to find packages missing git tags after publishing:

/**
 * Finds packages that are missing git tags
 * @param packages - Array of package objects
 * @param cwd - Working directory path
 * @param tool - Package manager tool type
 * @returns Promise resolving to array of packages needing tags
 */
function getUntaggedPackages(
  packages: Package[], 
  cwd: string, 
  tool: Tool
): Promise<PublishedResult[]>;

Access Control and Visibility

Package Access Configuration

type AccessType = "restricted" | "public";

// Configuration options
interface Config {
  access: "restricted" | "public";  // Default access level
  privatePackages: {
    version: boolean;  // Whether to version private packages
    tag: boolean;      // Whether to tag private packages  
  };
}

Per-Package Access Control

Individual packages can override global access settings:

{
  "name": "@myorg/public-package",
  "publishConfig": {
    "access": "public"
  }
}

Registry Configuration

Scoped Package Registries

Support for publishing scoped packages to custom registries:

interface RegistryInfo {
  scope?: string;    // Package scope (e.g., "@myorg")
  registry: string;  // Registry URL
}

Registry URL Resolution

// .npmrc configuration examples
registry=https://registry.npmjs.org/
@myorg:registry=https://npm.myorg.com/
//npm.myorg.com/:_authToken=${NPM_TOKEN}

Publishing Workflow

Standard Publishing Flow

  1. Validation: Check that packages are ready for publishing
  2. Registry Check: Verify package doesn't already exist at target version
  3. Authentication: Handle 2FA tokens and registry authentication
  4. Publishing: Upload packages to registry with proper access settings
  5. Git Tagging: Create git tags for successfully published packages
  6. Cleanup: Update local state and cleanup temporary files

Prerelease Publishing

For packages in prerelease mode:

// Prerelease packages use the prerelease tag
// Example: 1.0.0-beta.1 published with tag "beta"
await publish(cwd, { tag: "beta" }, config);

Snapshot Publishing

Snapshot releases are published with temporary versions:

// Snapshot versions like 0.0.0-20231201-abc1234
// Published with "snapshot" tag by default
await publish(cwd, { tag: "snapshot" }, config);

Error Handling and Recovery

Common Publishing Errors

  • Authentication failures: Invalid or expired tokens
  • Version conflicts: Package version already exists in registry
  • Network issues: Registry connectivity problems
  • Permission errors: Insufficient publish permissions

Retry Logic

The publishing system includes built-in retry logic for transient failures:

// Automatic retry for network-related failures
// Manual retry prompts for authentication issues
// Graceful degradation for partial publish failures

Partial Failure Handling

When publishing multiple packages, the system handles partial failures gracefully:

interface PublishedResult {
  name: string;
  newVersion: string;
  published: boolean;
}

// Results indicate which packages succeeded/failed
// Failed packages can be retried individually
// Git tags are only created for successfully published packages

Configuration Options

Publishing Configuration

{
  "access": "restricted",
  "privatePackages": {
    "version": true,
    "tag": false
  }
}

Custom Publish Scripts

Integration with custom publish workflows:

{
  "scripts": {
    "changeset:publish": "changeset publish",
    "changeset:publish:beta": "changeset publish --tag beta",
    "changeset:publish:dry": "changeset publish --dry-run"
  }
}

Types

interface PublishOptions {
  registry?: string;
  tag?: string;
  access?: AccessType;
  dryRun?: boolean;
}

interface PublishedResult {
  name: string;
  newVersion: string;
  published: boolean;
}

type Tool = "yarn" | "npm" | "pnpm";

interface PreState {
  mode: "pre";
  tag: string;
  initialVersions: Record<string, string>;
  changesets: string[];
}

Install with Tessl CLI

npx tessl i tessl/npm-changesets--cli

docs

changeset-creation.md

commands.md

index.md

prerelease.md

publishing.md

status-monitoring.md

utilities.md

version-management.md

tile.json