CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pnpm--npm-resolver

Resolver for npm-hosted packages with caching, offline support, and registry authentication

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

package-resolution.mddocs/

Package Resolution

The package resolution system provides comprehensive functionality for resolving npm packages from registries with support for caching, offline operation, and local package fallbacks.

Capabilities

Creating a Resolver

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;
}

Resolver Function

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;
}

Resolution Result

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';
}

Usage Examples

Basic Resolution

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}`);
}

Resolution with Version Range

// 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()
  }
);

Offline Resolution

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()
  }
);

Local Package Fallback

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}`);
}

Error Handling

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);
  }
}

Configuration with Authentication

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

docs

index.md

metadata-management.md

package-resolution.md

version-selection.md

tile.json