A better npm publish tool with automated workflows, version bumping, testing, and git integration
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
NPM registry interactions including package validation, publishing, 2FA management, and error handling for the publishing workflow.
Functions for retrieving NPM registry and package information.
/**
* Get the current npm version
* @returns Promise resolving to npm version string
*/
function version(): Promise<string>;
/**
* Check NPM registry connection
* @returns Promise that resolves if connection is successful
* @throws Error if unable to connect to registry
*/
function checkConnection(): Promise<void>;
/**
* Get the current npm username
* @param options - Configuration options
* @param options.externalRegistry - True if using external registry
* @returns Promise resolving to npm username
*/
function username(options: {externalRegistry?: boolean}): Promise<string>;
/**
* Check if package name is available on npm registry
* @param package_ - Package object with name property
* @returns Promise resolving to availability information
*/
function isPackageNameAvailable(package_: {name: string}): Promise<{
isAvailable: boolean;
isUnknown: boolean;
}>;
/**
* Get package collaborators/maintainers
* @param package_ - Package object with name property
* @returns Promise resolving to JSON string of collaborator information, or false if package doesn't exist
*/
function collaborators(package_: {name: string}): Promise<string | false>;
/**
* Get prerelease distribution tags for a package
* @param packageName - Name of the package
* @returns Promise resolving to array of prerelease tags
*/
function prereleaseTags(packageName: string): Promise<string[]>;Usage Examples:
import * as npm from "np/source/npm/util.js";
// Check npm environment
const npmVersion = await npm.version();
const currentUser = await npm.username({externalRegistry: false});
console.log(`NPM version: ${npmVersion}`);
console.log(`Logged in as: ${currentUser}`);
// Validate package name
const availability = await npm.isPackageNameAvailable({name: "my-package"});
if (availability.isAvailable) {
console.log("Package name is available - first publish");
} else if (availability.isUnknown) {
console.warn("Could not determine package availability");
} else {
console.log("Package exists - updating existing package");
}
// Check collaborators
const collaboratorInfo = await npm.collaborators({name: "my-package"});
if (collaboratorInfo) {
const maintainers = JSON.parse(collaboratorInfo);
console.log(`Package maintainers: ${Object.keys(maintainers).length}`);
} else {
console.log("Package does not exist");
}Functions for validating NPM environment and package configuration.
/**
* Verify npm version meets minimum requirements
* @throws Error if npm version is too old
*/
function verifyRecentNpmVersion(): Promise<void>;
/**
* Check if package uses external npm registry
* @param package_ - Package object with publishConfig or registry info
* @returns True if using external registry
*/
function isExternalRegistry(package_: object): boolean;
/**
* Check ignore strategy for npm publishing
* @param files - Package files configuration
* @param rootDirectory - Project root directory
* @returns Promise resolving to ignore strategy information
*/
function checkIgnoreStrategy(
files: {files?: string[]},
rootDirectory: string
): Promise<object>;
/**
* Get list of files that will be packed by npm
* @param rootDirectory - Project root directory
* @returns Promise resolving to array of file paths
*/
function getFilesToBePacked(rootDirectory: string): Promise<string[]>;Usage Examples:
import * as npm from "np/source/npm/util.js";
// Validate npm environment
await npm.verifyRecentNpmVersion(); // Throws if npm < 9
// Check registry configuration
const isExternal = npm.isExternalRegistry(packageJson);
if (isExternal) {
console.log("Using external registry");
}
// Analyze package files
const filesToPack = await npm.getFilesToBePacked(process.cwd());
console.log(`${filesToPack.length} files will be published`);
// Check ignore configuration
const ignoreInfo = await npm.checkIgnoreStrategy(
{files: packageJson.files},
process.cwd()
);Functions for executing NPM publish operations.
/**
* Generate npm publish command arguments
* @param options - Publishing options
* @returns Array of command line arguments for npm publish
*/
function getPackagePublishArguments(options: {
tag?: string;
contents?: string;
otp?: string;
[key: string]: any;
}): string[];
/**
* Execute npm publish command
* @param arguments_ - Command arguments from getPackagePublishArguments
* @returns Child process (execa) that can be awaited or used with streams
*/
function runPublish(arguments_: string[]): ChildProcess;Usage Examples:
import { getPackagePublishArguments, runPublish } from "np/source/npm/publish.js";
// Generate publish arguments
const publishArgs = getPackagePublishArguments({
tag: "beta",
contents: "dist",
otp: "123456"
});
// Result: ["publish", "dist", "--tag", "beta", "--otp", "123456"]
// Execute publish
const publishProcess = runPublish(publishArgs);
// Stream output
publishProcess.stdout.on('data', (data) => {
console.log(data.toString());
});
publishProcess.stderr.on('data', (data) => {
console.error(data.toString());
});
// Promise-based usage
try {
await publishProcess;
console.log('Successfully published to npm');
} catch (error) {
console.error('Publish failed:', error.message);
}Functions for managing 2FA on npm packages.
/**
* Generate arguments for enabling 2FA on a package
* @param packageName - Name of the package
* @param options - Configuration options
* @param options.otp - One-time password for authentication
* @returns Promise resolving to npm access command arguments
*/
function getEnable2faArguments(
packageName: string,
options: {otp?: string}
): Promise<string[]>;
/**
* Attempt to enable 2FA on a package with user interaction
* @param task - Listr task instance for user interaction
* @param packageName - Name of the package
* @param options - Configuration options
* @returns Promise that resolves when 2FA is enabled
*/
function tryEnable2fa(
task: object,
packageName: string,
options: {otp?: string}
): Promise<void>;Usage Examples:
import enable2fa, { getEnable2faArguments } from "np/source/npm/enable-2fa.js";
// Generate 2FA command
const args = await getEnable2faArguments("my-package", {otp: "123456"});
// Result: ["access", "2fa-required", "my-package", "--otp", "123456"]
// Enable 2FA in task context
await enable2fa(listrTask, "my-package", {otp: userOtp});Advanced error handling for npm publish operations.
/**
* Handle npm publish errors with OTP retry logic
* @param error - Error from npm publish command
* @param task - Listr task for user interaction
* @param retryFn - Function to retry publish with OTP
* @returns Promise that handles error and retry logic
*/
function handleNpmError(
error: Error,
task: object,
retryFn: (otp: string) => ChildProcess
): Promise<void>;Usage Examples:
import handleNpmError from "np/source/npm/handle-npm-error.js";
import { runPublish, getPackagePublishArguments } from "np/source/npm/publish.js";
// Use error handling in publish workflow
const publishStream = from(runPublish(getPackagePublishArguments(options)))
.pipe(
catchError(error => handleNpmError(error, task, (otp) => {
// Retry with OTP
const argsWithOtp = getPackagePublishArguments({...options, otp});
return runPublish(argsWithOtp);
}))
);NPM validation steps before publishing:
NPM operations during publishing:
NPM operations after successful publishing:
NPM publish supports various options:
const options = {
tag: "beta", // Publish under beta tag
contents: "dist", // Publish from dist directory
otp: "123456", // One-time password for 2FA
access: "public", // Package access level
registry: "custom" // Custom registry URL
};NPM packages can have different access levels:
/**
* Get npm package access information
* @param name - Package name
* @returns Promise resolving to access information
*/
function getNpmPackageAccess(name: string): Promise<{
access: 'public' | 'restricted';
[key: string]: any;
}>;Access Types:
Handle scoped package publishing:
// Scoped package names
"@myorg/my-package"
"@username/project-name"
// Require explicit public access
const publishArgs = getPackagePublishArguments({
access: "public" // Required for public scoped packages
});Standard npm registry configuration:
// Default npm registry
"https://registry.npmjs.org/"
// Package manager detection
const isNpm = packageManager.id === 'npm';
const registryUrl = isNpm ? undefined : packageManager.registry;Support for external npm registries:
// Custom registry in package.json
{
"publishConfig": {
"registry": "https://npm.example.com/"
}
}
// Detection
const isExternal = npm.isExternalRegistry(packageJson);
if (isExternal) {
// Disable 2FA setup
// Adjust publish commands
// Handle authentication differently
}Enterprise registry considerations:
Authentication Errors:
Publishing Errors:
Validation Errors:
NPM error handling strategies:
// OTP retry for 2FA
if (error.code === 'EOTP') {
const otp = await promptForOTP();
return retryPublish({...options, otp});
}
// Network retry
if (error.code === 'ENOTFOUND') {
await delay(1000);
return retryPublish(options);
}
// Permission error guidance
if (error.code === 'E403') {
throw new Error('Permission denied. Run "npm login" or check package ownership');
}NPM operations provide detailed debug information:
Install with Tessl CLI
npx tessl i tessl/npm-np