0
# Package Resolution
1
2
The package resolution system provides comprehensive functionality for resolving npm packages from registries with support for caching, offline operation, and local package fallbacks.
3
4
## Capabilities
5
6
### Creating a Resolver
7
8
The main factory function creates a configured resolver instance.
9
10
```typescript { .api }
11
/**
12
* Creates a package resolver with the specified configuration
13
* @param opts - Configuration options for the resolver
14
* @returns Configured resolver function
15
* @throws TypeError when required options are missing or invalid
16
*/
17
function createResolveFromNpm(opts: ResolverOptions): ResolveFunction;
18
19
interface ResolverOptions {
20
/** SSL certificate for HTTPS requests */
21
cert?: string;
22
/** Whether to fetch full package metadata (default: false) */
23
fullMetadata?: boolean;
24
/** SSL private key for HTTPS requests */
25
key?: string;
26
/** Certificate authority bundle */
27
ca?: string;
28
/** Whether to enforce strict SSL verification */
29
strictSsl?: boolean;
30
/** Raw npm configuration object (required) */
31
rawNpmConfig: object;
32
/** Metadata cache instance (required) */
33
metaCache: PackageMetaCache;
34
/** Store path for cached package data (required) */
35
store: string;
36
/** HTTP proxy URL */
37
proxy?: string;
38
/** HTTPS proxy URL (takes precedence over proxy) */
39
httpsProxy?: string;
40
/** Local network address to bind to */
41
localAddress?: string;
42
/** User agent string for requests */
43
userAgent?: string;
44
/** Enable offline mode */
45
offline?: boolean;
46
/** Prefer cached data when available */
47
preferOffline?: boolean;
48
/** Number of retry attempts for failed requests */
49
fetchRetries?: number;
50
/** Exponential backoff factor for retries */
51
fetchRetryFactor?: number;
52
/** Minimum timeout between retries (ms) */
53
fetchRetryMintimeout?: number;
54
/** Maximum timeout between retries (ms) */
55
fetchRetryMaxtimeout?: number;
56
}
57
```
58
59
### Resolver Function
60
61
The resolver function returned by `createResolveFromNpm` handles individual package resolution requests.
62
63
```typescript { .api }
64
/**
65
* Resolves a package dependency from npm registry
66
* @param wantedDependency - Package specification to resolve
67
* @param opts - Resolution options including registry and preferences
68
* @returns Promise resolving to package resolution result or null if not found
69
*/
70
type ResolveFunction = (
71
wantedDependency: WantedDependency,
72
opts: ResolveOptions
73
) => Promise<ResolveResult | null>;
74
75
interface WantedDependency {
76
/** Package alias/name */
77
alias?: string;
78
/** Version preference (version, range, or tag) */
79
pref?: string;
80
}
81
82
interface ResolveOptions {
83
/** Default tag to use when no preference specified (default: 'latest') */
84
defaultTag?: string;
85
/** Whether to perform a dry run without side effects */
86
dryRun?: boolean;
87
/** Registry URL to resolve from (required) */
88
registry: string;
89
/** Preferred versions for specific packages */
90
preferredVersions?: {
91
[packageName: string]: {
92
selector: string;
93
type: 'version' | 'range' | 'tag';
94
};
95
};
96
/** Project root prefix for local package resolution */
97
prefix: string;
98
/** Local packages available for fallback resolution */
99
localPackages?: LocalPackages;
100
}
101
```
102
103
### Resolution Result
104
105
The resolver returns detailed information about the resolved package.
106
107
```typescript { .api }
108
interface ResolveResult {
109
/** Unique package identifier */
110
id: string;
111
/** Latest version available in registry */
112
latest: string;
113
/** Normalized preference used for resolution */
114
normalizedPref?: string;
115
/** Complete package manifest */
116
package: PackageInRegistry;
117
/** Resolution metadata */
118
resolution: {
119
/** Package integrity hash */
120
integrity: string;
121
/** Registry URL used for resolution */
122
registry: string;
123
/** Tarball download URL */
124
tarball: string;
125
} | {
126
/** Local directory path for local packages */
127
directory: string;
128
/** Resolution type indicator */
129
type: 'directory';
130
};
131
/** How the package was resolved */
132
resolvedVia: 'npm-registry' | 'local-filesystem';
133
}
134
```
135
136
## Usage Examples
137
138
### Basic Resolution
139
140
```typescript
141
import createResolveFromNpm from '@pnpm/npm-resolver';
142
143
const resolve = createResolveFromNpm({
144
metaCache: new Map(),
145
store: './pnpm-store',
146
rawNpmConfig: {
147
registry: 'https://registry.npmjs.org/',
148
},
149
});
150
151
// Resolve exact version
152
const result = await resolve(
153
{ alias: 'lodash', pref: '4.17.21' },
154
{
155
registry: 'https://registry.npmjs.org/',
156
prefix: process.cwd()
157
}
158
);
159
160
if (result) {
161
console.log(`Resolved: ${result.package.name}@${result.package.version}`);
162
console.log(`Tarball: ${result.resolution.tarball}`);
163
}
164
```
165
166
### Resolution with Version Range
167
168
```typescript
169
// Resolve using semver range
170
const rangeResult = await resolve(
171
{ alias: 'express', pref: '^4.0.0' },
172
{
173
registry: 'https://registry.npmjs.org/',
174
prefix: process.cwd()
175
}
176
);
177
178
// Resolve using tag
179
const tagResult = await resolve(
180
{ alias: 'react', pref: 'beta' },
181
{
182
registry: 'https://registry.npmjs.org/',
183
prefix: process.cwd()
184
}
185
);
186
```
187
188
### Offline Resolution
189
190
```typescript
191
const offlineResolve = createResolveFromNpm({
192
metaCache: existingCache,
193
store: './pnpm-store',
194
offline: true,
195
rawNpmConfig: {
196
registry: 'https://registry.npmjs.org/',
197
},
198
});
199
200
// Will only resolve from cache
201
const cachedResult = await offlineResolve(
202
{ alias: 'axios', pref: '0.27.0' },
203
{
204
registry: 'https://registry.npmjs.org/',
205
prefix: process.cwd()
206
}
207
);
208
```
209
210
### Local Package Fallback
211
212
```typescript
213
const localPackages = {
214
'my-lib': {
215
'1.0.0': {
216
directory: '/path/to/my-lib',
217
package: { name: 'my-lib', version: '1.0.0' }
218
}
219
}
220
};
221
222
const result = await resolve(
223
{ alias: 'my-lib', pref: '1.0.0' },
224
{
225
registry: 'https://registry.npmjs.org/',
226
prefix: process.cwd(),
227
localPackages
228
}
229
);
230
231
// May resolve from local filesystem if registry fails
232
if (result?.resolvedVia === 'local-filesystem') {
233
console.log(`Using local package at: ${result.resolution.directory}`);
234
}
235
```
236
237
### Error Handling
238
239
```typescript
240
try {
241
const result = await resolve(
242
{ alias: 'nonexistent-package', pref: '1.0.0' },
243
{
244
registry: 'https://registry.npmjs.org/',
245
prefix: process.cwd()
246
}
247
);
248
249
if (!result) {
250
console.log('Package not found');
251
}
252
} catch (error) {
253
if (error.code === 'ERR_PNPM_NO_MATCHING_VERSION') {
254
console.log('No matching version found');
255
console.log('Available metadata:', error.packageMeta);
256
} else {
257
console.error('Resolution failed:', error.message);
258
}
259
}
260
```
261
262
### Configuration with Authentication
263
264
```typescript
265
const authenticatedResolve = createResolveFromNpm({
266
metaCache: new Map(),
267
store: './pnpm-store',
268
rawNpmConfig: {
269
registry: 'https://registry.npmjs.org/',
270
'//registry.npmjs.org/:_authToken': 'npm_token_here',
271
},
272
fetchRetries: 3,
273
fetchRetryFactor: 2,
274
fetchRetryMintimeout: 1000,
275
fetchRetryMaxtimeout: 10000,
276
});
277
```