Resolver for npm-hosted packages with caching, offline support, and registry authentication
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The package resolution system provides comprehensive functionality for resolving npm packages from registries with support for caching, offline operation, and local package fallbacks.
The main factory function creates a configured resolver instance.
/**
* Creates a package resolver with the specified configuration
* @param opts - Configuration options for the resolver
* @returns Configured resolver function
* @throws TypeError when required options are missing or invalid
*/
function createResolveFromNpm(opts: ResolverOptions): ResolveFunction;
interface ResolverOptions {
/** SSL certificate for HTTPS requests */
cert?: string;
/** Whether to fetch full package metadata (default: false) */
fullMetadata?: boolean;
/** SSL private key for HTTPS requests */
key?: string;
/** Certificate authority bundle */
ca?: string;
/** Whether to enforce strict SSL verification */
strictSsl?: boolean;
/** Raw npm configuration object (required) */
rawNpmConfig: object;
/** Metadata cache instance (required) */
metaCache: PackageMetaCache;
/** Store path for cached package data (required) */
store: string;
/** HTTP proxy URL */
proxy?: string;
/** HTTPS proxy URL (takes precedence over proxy) */
httpsProxy?: string;
/** Local network address to bind to */
localAddress?: string;
/** User agent string for requests */
userAgent?: string;
/** Enable offline mode */
offline?: boolean;
/** Prefer cached data when available */
preferOffline?: boolean;
/** Number of retry attempts for failed requests */
fetchRetries?: number;
/** Exponential backoff factor for retries */
fetchRetryFactor?: number;
/** Minimum timeout between retries (ms) */
fetchRetryMintimeout?: number;
/** Maximum timeout between retries (ms) */
fetchRetryMaxtimeout?: number;
}The resolver function returned by createResolveFromNpm handles individual package resolution requests.
/**
* Resolves a package dependency from npm registry
* @param wantedDependency - Package specification to resolve
* @param opts - Resolution options including registry and preferences
* @returns Promise resolving to package resolution result or null if not found
*/
type ResolveFunction = (
wantedDependency: WantedDependency,
opts: ResolveOptions
) => Promise<ResolveResult | null>;
interface WantedDependency {
/** Package alias/name */
alias?: string;
/** Version preference (version, range, or tag) */
pref?: string;
}
interface ResolveOptions {
/** Default tag to use when no preference specified (default: 'latest') */
defaultTag?: string;
/** Whether to perform a dry run without side effects */
dryRun?: boolean;
/** Registry URL to resolve from (required) */
registry: string;
/** Preferred versions for specific packages */
preferredVersions?: {
[packageName: string]: {
selector: string;
type: 'version' | 'range' | 'tag';
};
};
/** Project root prefix for local package resolution */
prefix: string;
/** Local packages available for fallback resolution */
localPackages?: LocalPackages;
}The resolver returns detailed information about the resolved package.
interface ResolveResult {
/** Unique package identifier */
id: string;
/** Latest version available in registry */
latest: string;
/** Normalized preference used for resolution */
normalizedPref?: string;
/** Complete package manifest */
package: PackageInRegistry;
/** Resolution metadata */
resolution: {
/** Package integrity hash */
integrity: string;
/** Registry URL used for resolution */
registry: string;
/** Tarball download URL */
tarball: string;
} | {
/** Local directory path for local packages */
directory: string;
/** Resolution type indicator */
type: 'directory';
};
/** How the package was resolved */
resolvedVia: 'npm-registry' | 'local-filesystem';
}import createResolveFromNpm from '@pnpm/npm-resolver';
const resolve = createResolveFromNpm({
metaCache: new Map(),
store: './pnpm-store',
rawNpmConfig: {
registry: 'https://registry.npmjs.org/',
},
});
// Resolve exact version
const result = await resolve(
{ alias: 'lodash', pref: '4.17.21' },
{
registry: 'https://registry.npmjs.org/',
prefix: process.cwd()
}
);
if (result) {
console.log(`Resolved: ${result.package.name}@${result.package.version}`);
console.log(`Tarball: ${result.resolution.tarball}`);
}// Resolve using semver range
const rangeResult = await resolve(
{ alias: 'express', pref: '^4.0.0' },
{
registry: 'https://registry.npmjs.org/',
prefix: process.cwd()
}
);
// Resolve using tag
const tagResult = await resolve(
{ alias: 'react', pref: 'beta' },
{
registry: 'https://registry.npmjs.org/',
prefix: process.cwd()
}
);const offlineResolve = createResolveFromNpm({
metaCache: existingCache,
store: './pnpm-store',
offline: true,
rawNpmConfig: {
registry: 'https://registry.npmjs.org/',
},
});
// Will only resolve from cache
const cachedResult = await offlineResolve(
{ alias: 'axios', pref: '0.27.0' },
{
registry: 'https://registry.npmjs.org/',
prefix: process.cwd()
}
);const localPackages = {
'my-lib': {
'1.0.0': {
directory: '/path/to/my-lib',
package: { name: 'my-lib', version: '1.0.0' }
}
}
};
const result = await resolve(
{ alias: 'my-lib', pref: '1.0.0' },
{
registry: 'https://registry.npmjs.org/',
prefix: process.cwd(),
localPackages
}
);
// May resolve from local filesystem if registry fails
if (result?.resolvedVia === 'local-filesystem') {
console.log(`Using local package at: ${result.resolution.directory}`);
}try {
const result = await resolve(
{ alias: 'nonexistent-package', pref: '1.0.0' },
{
registry: 'https://registry.npmjs.org/',
prefix: process.cwd()
}
);
if (!result) {
console.log('Package not found');
}
} catch (error) {
if (error.code === 'ERR_PNPM_NO_MATCHING_VERSION') {
console.log('No matching version found');
console.log('Available metadata:', error.packageMeta);
} else {
console.error('Resolution failed:', error.message);
}
}const authenticatedResolve = createResolveFromNpm({
metaCache: new Map(),
store: './pnpm-store',
rawNpmConfig: {
registry: 'https://registry.npmjs.org/',
'//registry.npmjs.org/:_authToken': 'npm_token_here',
},
fetchRetries: 3,
fetchRetryFactor: 2,
fetchRetryMintimeout: 1000,
fetchRetryMaxtimeout: 10000,
});Install with Tessl CLI
npx tessl i tessl/npm-pnpm--npm-resolver