A comprehensive cross-platform package management abstraction library that enables developers to programmatically install, manage, and find packages across multiple package managers including npm, yarn, pnpm, bun for Node.js projects, and CocoaPods for iOS projects.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core factory functions for creating and resolving package managers automatically based on project configuration and lockfiles.
Creates the appropriate package manager for a project by detecting lockfiles or using explicit configuration.
/**
* Creates a Node package manager from the provided options.
* If options are not provided, it will infer the package manager from lockfiles.
* When no package manager is found, it falls back to npm.
*
* @param projectRoot - The root directory of the project
* @param options - Configuration options with optional package manager selection
* @returns NodePackageManager instance appropriate for the project
*/
function createForProject(
projectRoot: string,
options?: NodePackageManagerForProject
): NodePackageManager;
type NodePackageManagerForProject = PackageManagerOptions &
Partial<Record<NodePackageManager['name'], boolean>>;Usage Examples:
import { createForProject } from '@expo/package-manager';
// Auto-detect from lockfiles
const manager = createForProject('/path/to/project');
// Force specific package manager
const npmManager = createForProject('/path/to/project', { npm: true });
const yarnManager = createForProject('/path/to/project', { yarn: true });
// With additional options
const silentManager = createForProject('/path/to/project', {
silent: true,
log: console.debug
});Resolves the package manager used by a project by checking for lockfiles.
/**
* Resolve the used node package manager for a project by checking the lockfile.
* This also tries to resolve the workspace root, if its part of a monorepo.
* Optionally, provide a preferred packager to only resolve that one specifically.
*
* @param projectRoot - The root directory of the project
* @param preferredManager - Optional preferred package manager to check for specifically
* @returns Package manager name or null if none found
*/
function resolvePackageManager(
projectRoot: string,
preferredManager?: NodePackageManager['name']
): NodePackageManager['name'] | null;Usage Examples:
import { resolvePackageManager } from '@expo/package-manager';
// Detect any package manager
const detected = resolvePackageManager('/path/to/project');
// Returns 'npm', 'yarn', 'pnpm', 'bun', or null
// Check for specific package manager
const hasYarn = resolvePackageManager('/path/to/project', 'yarn');
// Returns 'yarn' if yarn.lock exists, null otherwiseResolves the workspace root directory for monorepo projects.
/**
* Resolves the workspace root directory if the project is part of a monorepo
*
* @param projectRoot - The current project directory
* @returns Workspace root path or null if not in a workspace
*/
function resolveWorkspaceRoot(projectRoot: string): string | null;Usage Examples:
import { resolveWorkspaceRoot } from '@expo/package-manager';
const workspaceRoot = resolveWorkspaceRoot('/path/to/nested/project');
if (workspaceRoot) {
console.log(`Part of workspace at: ${workspaceRoot}`);
// Create manager for workspace root
const rootManager = createForProject(workspaceRoot);
}Package managers are resolved in a specific order based on lockfile presence.
const RESOLUTION_ORDER: NodePackageManager['name'][] = ['bun', 'yarn', 'npm', 'pnpm'];
const NPM_LOCK_FILE = 'package-lock.json';
const YARN_LOCK_FILE = 'yarn.lock';
const PNPM_LOCK_FILE = 'pnpm-lock.yaml';
const BUN_LOCK_FILE = 'bun.lockb';
const BUN_TEXT_LOCK_FILE = 'bun.lock';The resolution process:
preferredManager is specified, only check for that manager's lockfilesRESOLUTION_ORDER: bun → yarn → npm → pnpmnull if no lockfiles are foundUsage Examples:
import { RESOLUTION_ORDER, BUN_LOCK_FILE } from '@expo/package-manager';
// Check resolution order
console.log('Checking in order:', RESOLUTION_ORDER);
// Check for specific lockfiles
import fs from 'fs';
import path from 'path';
const hasBunLock = fs.existsSync(path.join(projectRoot, BUN_LOCK_FILE));