libnpmpack Programmatic Packing API
libnpmpack provides the programmatic interface for creating tarballs of npm packages, mirroring the functionality of the `npm pack` command-line tool. As an internal library of the npm CLI, it offers a robust and consistent way to prepare packages for distribution, including handling `.npmignore`, `.gitignore`, and package lifecycle scripts during the packing process. The current stable version of the `libnpmpack` package itself is 9.1.5, though it is often consumed as part of the broader npm CLI, which follows its own release schedule (e.g., v10.x and v11.x branches) and sees frequent updates. Its release cadence is tightly coupled with the npm CLI's monorepo development. A key differentiator is that it's the authoritative, low-level implementation for `npm pack`, ensuring compatibility with npm's official packing logic, unlike third-party alternatives which might deviate in edge cases. It focuses on encapsulating the complex logic of package bundling and file inclusion rules.
Common errors
-
ERR_REQUIRE_ESM: require() of ES Module ...libnpmpack/index.js from ... not supported.
cause Attempting to import `libnpmpack` using CommonJS `require()` syntax in a Node.js environment where the package is treated as an ES Module.fixMigrate your project to use ES Module `import` syntax: `import { pack } from 'libnpmpack';`. Ensure your `package.json` specifies `"type": "module"` or use `.mjs` file extensions for your source files. -
TypeError: Cannot destructure property 'pack' of 'libnpmpack__default.default' as it is undefined.
cause Incorrect import statement, often trying to destructure `pack` from a default import when it's a named export, or vice versa.fixVerify the import style. For `libnpmpack`, `pack` is a named export: `import { pack } from 'libnpmpack';`. -
Error: EACCES: permission denied, open '.../my-package-1.0.0.tgz'
cause The Node.js process does not have sufficient write permissions to create the tarball in the specified `packDestination` or the current working directory.fixEnsure the directory where the tarball is to be created has appropriate write permissions for the user running the Node.js process, or specify a different `packDestination` with adequate permissions.
Warnings
- breaking The `libnpmpack` package, being an internal component of the npm CLI, strictly enforces Node.js engine requirements. As of version 9.x, it requires Node.js `^20.17.0 || >=22.9.0`. Older Node.js versions will result in runtime errors.
- gotcha As an internal library, `libnpmpack`'s API might not maintain the same level of stability guarantees for external consumers as public-facing npm packages. Minor version bumps of `libnpmpack` or the encompassing `npm` CLI could introduce breaking changes without explicit semver declarations in `libnpmpack` itself, as its primary consumers are other npm CLI components.
- gotcha Understanding npm's file inclusion rules (e.g., how `.npmignore`, `files` array in `package.json`, and `.gitignore` interact) is crucial. Misconfiguration can lead to missing essential files or including unintended ones in the packed tarball.
Install
-
npm install libnpmpack -
yarn add libnpmpack -
pnpm add libnpmpack
Imports
- pack
const pack = require('libnpmpack')import { pack } from 'libnpmpack' - PackOptions
import type { PackOptions } from 'libnpmpack'
Quickstart
import { pack } from 'libnpmpack';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { promises as fs } from 'fs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const projectRoot = join(__dirname, 'my-test-package');
const outputPath = join(__dirname, 'output');
async function createAndPackPackage() {
await fs.mkdir(projectRoot, { recursive: true });
await fs.mkdir(outputPath, { recursive: true });
await fs.writeFile(
join(projectRoot, 'package.json'),
JSON.stringify({
name: 'my-packed-package',
version: '1.0.0',
main: 'index.js',
files: ['index.js', 'data/'],
scripts: {
test: 'echo "Error: no test specified" && exit 1'
}
}, null, 2)
);
await fs.writeFile(join(projectRoot, 'index.js'), 'console.log("Hello from packed package!");');
await fs.mkdir(join(projectRoot, 'data'), { recursive: true });
await fs.writeFile(join(projectRoot, 'data', 'config.txt'), 'some config data');
await fs.writeFile(join(projectRoot, '.npmignore'), 'node_modules\n.git');
console.log(`Created test package at: ${projectRoot}`);
try {
const tarballs = await pack(projectRoot, {
// Optional: Specify a target directory for the tarball
// Default is current working directory
packDestination: outputPath,
// log: console // You can pass a logger object if needed
});
console.log(`Successfully packed package(s) to:`);
tarballs.forEach(tarballPath => console.log(`- ${tarballPath}`));
} catch (error) {
console.error('Failed to pack package:', error);
process.exit(1);
} finally {
// Clean up created files/directories
await fs.rm(projectRoot, { recursive: true, force: true });
await fs.rm(outputPath, { recursive: true, force: true });
console.log('Cleaned up test directories.');
}
}
createAndPackPackage();