Comprehensive node_modules tree management library for npm dependency resolution and reification
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The Shrinkwrap class manages package-lock.json and npm-shrinkwrap.json files, providing support for multiple lockfile versions with bidirectional conversion and metadata preservation.
Creates a new Shrinkwrap instance for managing lockfiles.
/**
* Create a new Shrinkwrap instance
* @param options - Shrinkwrap configuration options
*/
constructor(options?: ShrinkwrapOptions): Shrinkwrap;
interface ShrinkwrapOptions {
/** Project path, defaults to current directory */
path?: string;
/** Lockfile version (1, 2, or 3) */
lockfileVersion?: 1 | 2 | 3;
/** JSON indentation, default 2 */
indent?: number;
/** Line ending character, default '\n' */
newline?: string;
/** Only use npm-shrinkwrap.json, default false */
shrinkwrapOnly?: boolean;
/** Hidden lockfile, default false */
hiddenLockfile?: boolean;
/** Resolve options */
resolveOptions?: object;
}Usage Example:
const { Shrinkwrap } = require('@npmcli/arborist');
// Create with default options
const shrinkwrap = new Shrinkwrap({
path: '/path/to/project',
lockfileVersion: 3
});Factory methods for loading and creating Shrinkwrap instances.
/**
* Load shrinkwrap from disk
* @param options - Loading options
* @returns Promise resolving to Shrinkwrap instance
*/
static load(options?: ShrinkwrapOptions): Promise<Shrinkwrap>;
/**
* Create new shrinkwrap (reset existing)
* @param options - Creation options
* @returns Promise resolving to new Shrinkwrap instance
*/
static reset(options?: ShrinkwrapOptions): Promise<Shrinkwrap>;
/**
* Extract metadata from a node for lockfile storage
* @param node - Node to extract metadata from
* @param path - Path for metadata storage
* @param options - Extraction options
* @returns Metadata object
*/
static metaFromNode(node: Node, path: string, options?: object): object;Usage Examples:
// Load existing lockfile
const shrinkwrap = await Shrinkwrap.load({
path: '/path/to/project'
});
// Create new lockfile
const newShrinkwrap = await Shrinkwrap.reset({
path: '/path/to/project',
lockfileVersion: 3
});
// Extract metadata from node
const metadata = Shrinkwrap.metaFromNode(node, 'node_modules/package');Static properties available on the Shrinkwrap class.
interface ShrinkwrapStatics {
/** Default lockfile version */
static defaultLockfileVersion: 3;
/** Key ordering for JSON serialization */
static keyOrder: string[];
}Properties defining the shrinkwrap configuration and behavior.
interface ShrinkwrapConfiguration {
/** Project path */
path: string;
/** Lockfile filename (package-lock.json or npm-shrinkwrap.json) */
filename: string;
/** Current lockfile version */
lockfileVersion: number;
/** Original version when loaded from disk */
originalLockfileVersion: number;
/** JSON indentation */
indent: number;
/** Line ending character */
newline: string;
/** Filename type */
type: string;
}Usage Example:
console.log(`Lockfile: ${shrinkwrap.filename}`);
console.log(`Version: ${shrinkwrap.lockfileVersion}`);
console.log(`Original version: ${shrinkwrap.originalLockfileVersion}`);Properties indicating the current state and content of the shrinkwrap.
interface ShrinkwrapState {
/** Lockfile data object */
data: object;
/** Associated tree */
tree: Node | null;
/** Was loaded from existing file */
loadedFromDisk: boolean;
/** Is hidden lockfile */
hiddenLockfile: boolean;
/** Only npm-shrinkwrap.json */
shrinkwrapOnly: boolean;
/** Loading error if any */
loadingError: Error | null;
/** Yarn lock data */
yarnLock: any | null;
/** Is ancient lockfile format */
ancientLockfile: boolean;
/** Resolve options */
resolveOptions: object;
}Usage Example:
// Check shrinkwrap state
if (shrinkwrap.loadedFromDisk) {
console.log('Loaded existing lockfile');
} else {
console.log('Created new lockfile');
}
if (shrinkwrap.loadingError) {
console.error('Loading error:', shrinkwrap.loadingError.message);
}
// Access lockfile data
console.log('Lockfile data:', shrinkwrap.data);Methods for loading from and saving to disk.
/**
* Load shrinkwrap data from disk
* @returns Promise that resolves when loading is complete
*/
async load(): Promise<void>;
/**
* Save shrinkwrap data to disk
* @param options - Save options
* @returns Promise that resolves when saving is complete
*/
async save(options?: SaveOptions): Promise<void>;
/**
* Reset to empty state
*/
reset(): void;
/**
* Commit pending changes
*/
commit(): void;
interface SaveOptions {
/** Format the JSON output */
format?: boolean;
}Usage Examples:
// Load from disk
await shrinkwrap.load();
// Save to disk
await shrinkwrap.save();
// Save with formatting
await shrinkwrap.save({ format: true });
// Reset to empty state
shrinkwrap.reset();
// Commit pending changes
shrinkwrap.commit();Methods for accessing and modifying lockfile data.
/**
* Get node metadata by path
* @param nodePath - Path to node in lockfile
* @returns Metadata object or undefined
*/
get(nodePath: string): any;
/**
* Delete node metadata by path
* @param nodePath - Path to node in lockfile
*/
delete(nodePath: string): void;
/**
* Add node to shrinkwrap
* @param node - Node to add
*/
add(node: Node): void;
/**
* Add edge metadata to shrinkwrap
* @param edge - Edge to add metadata for
*/
addEdge(edge: Edge): void;Usage Examples:
// Get metadata for a specific package
const metadata = shrinkwrap.get('node_modules/express');
if (metadata) {
console.log(`Express metadata:`, metadata);
}
// Add node to lockfile
shrinkwrap.add(expressNode);
// Add edge metadata
shrinkwrap.addEdge(dependencyEdge);
// Remove package from lockfile
shrinkwrap.delete('node_modules/old-package');Methods for converting shrinkwrap data to string representations.
/**
* Convert to string representation
* @param options - String conversion options
* @returns JSON string representation
*/
toString(options?: object): string;
/**
* Convert to JSON representation
* @returns JSON object representation
*/
toJSON(): object;Usage Examples:
// Get JSON string
const jsonString = shrinkwrap.toString();
// Get formatted JSON string
const formattedString = shrinkwrap.toString({ format: true });
// Get JSON object
const jsonObject = shrinkwrap.toJSON();Methods for working with yarn.lock files alongside npm lockfiles.
/**
* Check a spec against yarn.lock
* @param spec - Package spec to check
* @param options - Check options
* @returns Yarn lock entry or null
*/
checkYarnLock(spec: string, options?: object): any;Usage Example:
// Check yarn.lock for package
const yarnEntry = shrinkwrap.checkYarnLock('express@^4.18.0');
if (yarnEntry) {
console.log('Found in yarn.lock:', yarnEntry);
}Methods for inferring and setting formatting options.
/**
* Infer formatting options from package.json
* @param packageJSONData - Package.json content
*/
inferFormattingOptions(packageJSONData: object): void;Usage Example:
// Infer formatting from package.json
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
shrinkwrap.inferFormattingOptions(packageJson);Original npm lockfile format with basic dependency tracking.
const v1Shrinkwrap = new Shrinkwrap({
lockfileVersion: 1,
path: '/project'
});Enhanced format with improved metadata and deduplication tracking.
const v2Shrinkwrap = new Shrinkwrap({
lockfileVersion: 2,
path: '/project'
});Latest format with workspace support and enhanced peer dependency tracking.
const v3Shrinkwrap = new Shrinkwrap({
lockfileVersion: 3,
path: '/project'
});Standard npm lockfile, committed to version control.
// Standard lockfile (default)
const packageLock = await Shrinkwrap.load({
path: '/project'
// Uses package-lock.json by default
});Published lockfile that gets included in npm packages.
// Shrinkwrap file (published)
const shrinkwrapFile = await Shrinkwrap.load({
path: '/project',
shrinkwrapOnly: true
});Special lockfiles for internal use cases.
// Hidden lockfile
const hiddenLock = new Shrinkwrap({
path: '/project',
hiddenLockfile: true
});// Load existing lockfile
const shrinkwrap = await Shrinkwrap.load({ path: '/project' });
// Add new dependency metadata
shrinkwrap.add(newPackageNode);
// Save updated lockfile
await shrinkwrap.save();// Load v2 lockfile
const oldShrinkwrap = await Shrinkwrap.load({ path: '/project' });
console.log(`Current version: ${oldShrinkwrap.lockfileVersion}`);
// Upgrade to v3
oldShrinkwrap.lockfileVersion = 3;
await oldShrinkwrap.save();// Sync shrinkwrap with tree
shrinkwrap.tree = rootNode;
// Add all nodes from tree
for (const node of rootNode.inventory.values()) {
shrinkwrap.add(node);
}
// Save synchronized lockfile
await shrinkwrap.save();Install with Tessl CLI
npx tessl i tessl/npm-npmcli--arborist