A better npm publish tool with automated workflows, version bumping, testing, and git integration
npx @tessl/cli install tessl/npm-np@10.2.0NP is an enhanced npm publishing tool that automates and improves the entire package publishing workflow. It provides an interactive CLI that ensures proper release management with version bumping, automated testing, git integration, and comprehensive validation.
npm install --global npFor programmatic usage:
import np from "np";CommonJS:
const np = require("np");# Interactive release with patch version bump
np
# Specify version increment
np minor
# Specific version
np 1.2.3
# Preview mode (dry run)
np --preview
# Skip tests and cleanup (not recommended)
np --yoloimport np from "np";
import { readPackage } from "np/source/util.js";
// Read package information first
const { package_, rootDirectory } = await readPackage();
// Basic usage with default options
const newPackage = await np("patch", {
cleanup: true,
tests: true,
publish: true,
preview: false
}, {
package_,
rootDirectory
});
console.log(`Published ${newPackage.name}@${newPackage.version}`);NP is built around several key components:
np function orchestrates the complete publishing pipelineThe main publishing function that orchestrates version bumping, testing, publishing, and git operations.
/**
* Main publishing function that handles the complete npm publishing workflow
* @param input - Version increment ('patch'|'minor'|'major'|'prerelease'|'prepatch'|'preminor'|'premajor') or specific version string (default: 'patch')
* @param options - Publishing configuration options (packageManager will be extracted separately)
* @param context - Package metadata and root directory context
* @returns Promise resolving to updated package.json data
*/
function np(
input?: string,
options?: Options & {packageManager?: PackageManagerConfig},
context?: {
package_: NormalizedPackageJson;
rootDirectory: string;
}
): Promise<NormalizedPackageJson>;Advanced semver version handling with validation, formatting, and increment operations.
class Version {
constructor(version: string, increment?: string, options?: object);
setFrom(input: string, options?: object): void;
format(options?: object): string;
satisfies(range: string): boolean;
isPrerelease(): boolean;
toString(): string;
}
const SEMVER_INCREMENTS: string[];Comprehensive git integration for branch validation, tagging, history management, and pushing.
// Git information
function latestTag(): Promise<string>;
function getCurrentBranch(): Promise<string>;
function defaultBranch(): Promise<string>;
function hasUpstream(): Promise<boolean>;
// Git validation
function verifyWorkingTreeIsClean(): Promise<void>;
function verifyCurrentBranchIsReleaseBranch(releaseBranch: string): Promise<void>;
function verifyRemoteHistoryIsClean(): Promise<void>;NPM registry interactions including package validation, publishing, and 2FA management.
// NPM information
function version(): Promise<string>;
function username(options: {externalRegistry?: boolean}): Promise<string>;
function isPackageNameAvailable(package_: object): Promise<{isAvailable: boolean; isUnknown: boolean}>;
// Publishing
function getPackagePublishArguments(options: Options): string[];
function runPublish(arguments_: string[]): ChildProcess;Multi-package-manager abstraction supporting npm, Yarn, pnpm, and Bun with unified configuration.
interface PackageManagerConfig {
id: string;
cli: string;
installCommand: [string, string[]];
installCommandNoLockfile: [string, string[]];
versionCommand(input: string): [string, string[]];
publishCommand?(args: string[]): [string, string[]];
throwOnExternalRegistry?: boolean;
}
function getPackageManagerConfig(rootDirectory: string, package_: object): PackageManagerConfig;
function findLockfile(rootDirectory: string, config: PackageManagerConfig): string | undefined;Flexible configuration system supporting file-based and CLI-based options.
/**
* Load np configuration from config files
* @param rootDirectory - Project root directory
* @returns Promise resolving to configuration object
*/
function getConfig(rootDirectory: string): Promise<object>;General utility functions for package analysis, file operations, and display formatting.
// Package utilities
function readPackage(packagePath?: string): Promise<{package_: object; rootDirectory: string}>;
function getNewFiles(rootDirectory: string): Promise<string[]>;
function getNewDependencies(newPackage: object, rootDirectory: string): Promise<string[]>;
// Display utilities
function linkifyIssues(url: string, message: string): string;
function linkifyCommit(url: string, commit: string): string;
function joinList(list: string[]): string;Internal task modules for the publishing workflow execution.
/**
* Pre-publish validation tasks
* @param input - Version input
* @param package_ - Package object
* @param options - Publishing options
* @param packageManager - Package manager configuration
* @returns Listr task list
*/
function prerequisiteTasks(input: string, package_: object, options: Options, packageManager: object): object;
/**
* Git workflow tasks
* @param options - Publishing options
* @returns Listr task list
*/
function gitTasks(options: Options): object;
/**
* GitHub release draft creation
* @param options - Publishing options
* @param package_ - Package object
* @param packageManager - Package manager configuration
* @returns Promise resolving when release draft is created
*/
function releaseTaskHelper(options: Options, package_: object, packageManager: object): Promise<void>;
/**
* Interactive UI and prompts
* @param options - Initial options
* @param context - Package context
* @returns Promise resolving to final confirmed options
*/
function ui(options: Options, context: {package_: object; rootDirectory: string}): Promise<Options>;interface Options {
// Version and publishing
version?: string; // Version increment or specific version
tag?: string; // npm dist-tag
contents?: string; // Subdirectory to publish
message?: string; // Version bump commit message
// Branch and git options
anyBranch?: boolean; // Allow publishing from any branch
branch?: string; // Release branch name
// Process control
cleanup?: boolean; // Clean node_modules before publish (default: true)
tests?: boolean; // Run tests before publish (default: true)
yolo?: boolean; // Skip cleanup and tests
publish?: boolean; // Actually publish to npm (default: true)
preview?: boolean; // Show tasks without executing
// Release options
releaseDraft?: boolean; // Create GitHub release draft (default: true)
releaseDraftOnly?: boolean; // Only create release draft
// Security and access
'2fa'?: boolean; // Enable 2FA on new packages (default: true)
// Package manager
packageManager?: string; // Force specific package manager
testScript?: string; // Custom test script name (default: 'test')
// Internal computed properties (set by np)
runPublish?: boolean; // Whether to actually publish
availability?: { // Package name availability
isAvailable: boolean;
isUnknown: boolean;
};
repoUrl?: string; // Repository URL
releaseNotes?: (tag: string) => string; // Release notes generator
confirm?: boolean; // User confirmation
}// Main types used across the API
interface NormalizedPackageJson {
name: string;
version: string;
private?: boolean;
packageManager?: string;
[key: string]: any;
}
interface ValidationError {
path: string;
message: string;
value: any;
}
interface GitPushResult {
reason?: string;
[key: string]: any;
}
interface ChildProcess {
stdout: ReadableStream;
stderr: ReadableStream;
kill(): void;
[key: string]: any;
}
type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
type SemverIncrement = 'patch' | 'minor' | 'major' | 'prepatch' | 'preminor' | 'premajor' | 'prerelease';
type ColorName = string; // Chalk color name or modifier name
interface PackageManagerConfig {
id: string;
cli: string;
installCommand: [string, string[]];
installCommandNoLockfile: [string, string[]];
versionCommand(input: string): [string, string[]];
publishCommand?(args: string[]): [string, string[]];
throwOnExternalRegistry?: boolean;
}