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
Flexible configuration system supporting file-based and CLI-based options with multiple configuration sources and formats.
Function for loading np configuration from various sources.
/**
* Load np configuration from config files using cosmiconfig
* @param rootDirectory - Project root directory to search from
* @returns Promise resolving to configuration object
*/
function getConfig(rootDirectory: string): Promise<object>;Usage Examples:
import getConfig from "np/source/config.js";
// Load configuration from project root
const npConfig = await getConfig(process.cwd());
console.log('Loaded configuration:', npConfig);
// Merge with CLI options
const finalOptions = {
...npConfig, // File-based config
...cliFlags, // CLI flags override file config
...defaultOptions // Defaults for unspecified options
};NP searches for configuration in multiple file formats using cosmiconfig:
JSON Configuration:
// .np-config.json
{
"cleanup": false,
"tests": true,
"releaseDraft": false,
"2fa": true,
"message": "Release v%s"
}JavaScript Configuration:
// .np-config.js
module.exports = {
cleanup: false,
tests: true,
releaseDraft: false,
'2fa': true,
message: 'Release v%s'
};
// ES modules
export default {
cleanup: false,
tests: true,
releaseDraft: false,
'2fa': true,
message: 'Release v%s'
};Package.json Configuration:
{
"name": "my-package",
"version": "1.0.0",
"np": {
"cleanup": false,
"tests": true,
"releaseDraft": false,
"2fa": true,
"message": "Release v%s"
}
}YAML Configuration:
# .np-config.yaml
cleanup: false
tests: true
releaseDraft: false
2fa: true
message: "Release v%s"Cosmiconfig searches for configuration files in this order:
.np-config.*np field$XDG_CONFIG_HOME/np/config.*Configuration files are loaded with this precedence (highest to lowest):
.np-config.json.np-config.js.np-config.yaml / .np-config.ymlpackage.json (np field)Configure the main publishing behavior:
{
// Version and publishing
"version": "patch", // Default version increment
"tag": "latest", // Default npm dist-tag
"contents": ".", // Directory to publish from
"message": "v%s", // Git commit message template
// Process control
"cleanup": true, // Clean node_modules before publish
"tests": true, // Run tests before publish
"yolo": false, // Skip cleanup and tests
"publish": true, // Actually publish to npm
"preview": false, // Dry-run mode
// Release options
"releaseDraft": true, // Create GitHub release draft
"releaseDraftOnly": false, // Only create release draft
// Package manager
"packageManager": "npm", // Force specific package manager
"testScript": "test" // Custom test script name
}Configure git behavior and branch restrictions:
{
// Branch options
"anyBranch": false, // Allow publishing from any branch
"branch": "main", // Specific release branch name
// Git workflow
"commit": true, // Create version commit
"tag": true, // Create git tag
"push": true, // Push to remote repository
// Message templates
"message": "Release v%s", // Commit message (%s = version)
"tagMessage": "v%s" // Tag message template
}Configure npm security and access settings:
{
// Security
"2fa": true, // Enable 2FA on new packages
"access": "public", // Package access level
// Registry
"registry": "https://registry.npmjs.org/", // Custom registry URL
"token": process.env.NPM_TOKEN // Authentication token
}Configure interactive prompts and output:
{
// Interactive behavior
"interactive": true, // Show interactive prompts
"confirm": true, // Require confirmation before publish
// Output control
"quiet": false, // Suppress non-essential output
"verbose": false, // Show detailed output
"renderer": "default" // Task renderer (default, verbose, silent)
}Configuration options are merged with this priority (highest to lowest):
--cleanup, --no-tests)NP_* prefixed variables// Default configuration
const defaults = {
cleanup: true,
tests: true,
publish: true,
releaseDraft: true,
'2fa': true
};
// File configuration (.np-config.json)
const fileConfig = {
cleanup: false,
releaseDraft: false,
message: "Release v%s"
};
// CLI flags
const cliFlags = {
tests: false, // --no-tests
preview: true // --preview
};
// Final merged configuration
const finalConfig = {
...defaults, // cleanup: true, tests: true, publish: true, releaseDraft: true, '2fa': true
...fileConfig, // cleanup: false (overrides), releaseDraft: false (overrides), message: "Release v%s" (new)
...cliFlags // tests: false (overrides), preview: true (new)
};
// Result: { cleanup: false, tests: false, publish: true, releaseDraft: false, '2fa': true, message: "Release v%s", preview: true }NP supports environment variables for sensitive configuration:
# Authentication
export NPM_TOKEN="npm_xxxxxxxxxxxx"
export NPM_CONFIG_REGISTRY="https://npm.example.com/"
# Git configuration
export GIT_AUTHOR_NAME="Release Bot"
export GIT_AUTHOR_EMAIL="bot@example.com"
export GIT_COMMITTER_NAME="Release Bot"
export GIT_COMMITTER_EMAIL="bot@example.com"
# CI/CD specific
export CI=true # Enables non-interactive mode
export NP_DRY_RUN=true # Enables preview mode
export NP_SKIP_TESTS=true # Skips test executionSpecial environment variable handling for CI/CD:
// Detect CI environment
const isCI = process.env.CI === 'true';
// Adjust configuration for CI
const ciConfig = {
interactive: !isCI, // Disable prompts in CI
confirm: !isCI, // Skip confirmation in CI
renderer: isCI ? 'verbose' : 'default' // Better CI output
};Configuration options are validated against a schema:
// Valid configuration
const validConfig = {
cleanup: true, // boolean
tests: true, // boolean
tag: "beta", // string
message: "v%s", // string with %s placeholder
packageManager: "npm" // enum: npm, yarn, pnpm, bun
};
// Invalid configuration (throws error)
const invalidConfig = {
cleanup: "yes", // Error: should be boolean
tests: 1, // Error: should be boolean
tag: 123, // Error: should be string
packageManager: "invalid" // Error: unknown package manager
};Type Errors:
{
"cleanup": "true" // Error: should be boolean, not string
}Value Errors:
{
"packageManager": "bower" // Error: unsupported package manager
}Format Errors:
{
"message": "Release" // Warning: should include %s placeholder
}Dynamic configuration based on environment:
// .np-config.js
module.exports = {
// Base configuration
cleanup: true,
tests: true,
// Environment-specific overrides
...(process.env.NODE_ENV === 'development' && {
preview: true,
releaseDraft: false
}),
...(process.env.CI && {
interactive: false,
confirm: false,
renderer: 'verbose'
})
};Custom message templates for different project types:
// .np-config.js
const packageJson = require('./package.json');
module.exports = {
// Custom message based on package type
message: packageJson.private
? 'Internal release v%s'
: 'Public release v%s',
// Skip 2FA for private packages
'2fa': !packageJson.private,
// Custom test script for different frameworks
testScript: packageJson.scripts.test ? 'test' : 'check'
};Configuration inheritance in monorepos:
// Root .np-config.json (workspace root)
{
"cleanup": true,
"tests": true,
"releaseDraft": false,
"2fa": true
}
// Package .np-config.json (packages/my-package/)
{
"releaseDraft": true, // Override for this package
"tag": "beta" // Package-specific tag
}
// Final configuration merges both filesEnable debug logging to troubleshoot configuration:
# Debug cosmiconfig loading
DEBUG=cosmiconfig np
# Debug np configuration
DEBUG=np:config np --previewView final merged configuration:
# Preview mode shows final configuration
np --preview
# Verbose output includes configuration details
np --preview --verboseFile Not Found:
.np-config.json not .np.config.json)Merge Conflicts:
Invalid Options:
Install with Tessl CLI
npx tessl i tessl/npm-np