0
# Resolve.exports
1
2
Resolve.exports is a tiny (952b), correct, general-purpose, and configurable "exports" and "imports" resolver for Node.js package.json fields without file-system reliance. It provides spec-compliant resolution of module paths based on conditional exports, supporting both CommonJS and ES modules.
3
4
## Package Information
5
6
- **Package Name**: resolve.exports
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install resolve.exports`
10
11
## Core Imports
12
13
```typescript
14
import { resolve, exports, imports, legacy } from "resolve.exports";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { resolve, exports, imports, legacy } = require("resolve.exports");
21
```
22
23
## Basic Usage
24
25
```typescript
26
import { resolve, exports } from "resolve.exports";
27
28
// Example package.json-like object
29
const pkg = {
30
name: "my-package",
31
exports: {
32
".": {
33
"import": "./dist/index.mjs",
34
"require": "./dist/index.js"
35
},
36
"./utils": {
37
"import": "./dist/utils.mjs",
38
"require": "./dist/utils.js"
39
}
40
}
41
};
42
43
// Resolve main entry point for ES modules
44
const result = resolve(pkg, ".", { require: false });
45
console.log(result); // ["./dist/index.mjs"]
46
47
// Resolve specific export for CommonJS
48
const utilsResult = exports(pkg, "./utils", { require: true });
49
console.log(utilsResult); // ["./dist/utils.js"]
50
```
51
52
## Capabilities
53
54
### Main Resolution Function
55
56
The primary entry point that automatically routes to exports() or imports() based on the entry value.
57
58
```typescript { .api }
59
/**
60
* Convenience helper that automatically routes to exports() or imports() based on input value
61
* @param pkg - Package.json-like object containing exports/imports
62
* @param input - Target entry identifier (defaults to ".")
63
* @param options - Resolution options
64
* @returns Array of resolved paths or void if no match
65
*/
66
function resolve<T = Package>(
67
pkg: T,
68
input?: string,
69
options?: Options
70
): Imports.Output | Exports.Output | void;
71
```
72
73
### Exports Resolution
74
75
Resolves package.json "exports" field mappings according to Node.js specification.
76
77
```typescript { .api }
78
/**
79
* Resolves package.json "exports" field mappings
80
* @param pkg - Package.json-like object containing exports
81
* @param input - Export specifier to resolve (defaults to ".")
82
* @param options - Resolution options
83
* @returns Array of resolved paths or void if no match
84
* @throws Error if entry not found or no matching conditions
85
*/
86
function exports<T = Package>(
87
pkg: T,
88
input?: string,
89
options?: Options
90
): Exports.Output | void;
91
```
92
93
**Usage Example:**
94
95
```typescript
96
const pkg = {
97
name: "example",
98
exports: {
99
".": {
100
"node": "./dist/node.js",
101
"browser": "./dist/browser.js",
102
"default": "./dist/index.js"
103
},
104
"./feature": "./dist/feature.js"
105
}
106
};
107
108
// Resolve for browser environment
109
const browserPath = exports(pkg, ".", { browser: true });
110
console.log(browserPath); // ["./dist/browser.js"]
111
112
// Resolve specific feature
113
const featurePath = exports(pkg, "./feature");
114
console.log(featurePath); // ["./dist/feature.js"]
115
```
116
117
### Imports Resolution
118
119
Resolves package.json "imports" field mappings for internal package imports starting with "#".
120
121
```typescript { .api }
122
/**
123
* Resolves package.json "imports" field mappings
124
* @param pkg - Package.json-like object containing imports
125
* @param input - Import specifier (must start with "#")
126
* @param options - Resolution options
127
* @returns Array of resolved paths or void if no match
128
* @throws Error if target not found or no matching conditions
129
*/
130
function imports<T = Package>(
131
pkg: T,
132
input: string,
133
options?: Options
134
): Imports.Output | void;
135
```
136
137
**Usage Example:**
138
139
```typescript
140
const pkg = {
141
name: "example",
142
imports: {
143
"#utils": {
144
"node": "./src/utils-node.js",
145
"browser": "./src/utils-browser.js"
146
},
147
"#config/*": "./config/*.json"
148
}
149
};
150
151
// Resolve internal import
152
const utilsPath = imports(pkg, "#utils", { browser: true });
153
console.log(utilsPath); // ["./src/utils-browser.js"]
154
155
// Resolve wildcard import
156
const configPath = imports(pkg, "#config/database");
157
console.log(configPath); // ["./config/database.json"]
158
```
159
160
### Legacy Resolution
161
162
Resolves legacy package.json fields ("main", "module", "browser") as fallback when exports are not available.
163
164
```typescript { .api }
165
/**
166
* Resolves legacy package.json fields (main, module, browser) as fallback
167
*/
168
function legacy<T = Package>(
169
pkg: T,
170
options: { browser: true; fields?: readonly string[] }
171
): Browser | void;
172
173
function legacy<T = Package>(
174
pkg: T,
175
options: { browser: string; fields?: readonly string[] }
176
): string | false | void;
177
178
function legacy<T = Package>(
179
pkg: T,
180
options: { browser: false; fields?: readonly string[] }
181
): string | void;
182
183
function legacy<T = Package>(
184
pkg: T,
185
options?: {
186
browser?: boolean | string;
187
fields?: readonly string[];
188
}
189
): Browser | string;
190
```
191
192
**Usage Example:**
193
194
```typescript
195
const pkg = {
196
name: "legacy-package",
197
main: "./lib/index.js",
198
module: "./lib/index.mjs",
199
browser: "./lib/browser.js"
200
};
201
202
// Get main entry for Node.js
203
const nodeEntry = legacy(pkg, { browser: false });
204
console.log(nodeEntry); // "./lib/index.js"
205
206
// Get browser entry
207
const browserEntry = legacy(pkg, { browser: true });
208
console.log(browserEntry); // "./lib/browser.js"
209
210
// Custom field priority
211
const customEntry = legacy(pkg, {
212
browser: false,
213
fields: ["module", "main"]
214
});
215
console.log(customEntry); // "./lib/index.mjs"
216
```
217
218
## Types
219
220
### Options Interface
221
222
Configuration options for resolution behavior.
223
224
```typescript { .api }
225
interface Options {
226
/**
227
* When true, adds the "browser" conditions.
228
* Otherwise the "node" condition is enabled.
229
* @default false
230
*/
231
browser?: boolean;
232
233
/**
234
* Any custom conditions to match.
235
* @note Array order does not matter. Priority is determined by the key-order of conditions defined within a package's imports/exports mapping.
236
* @default []
237
*/
238
conditions?: readonly string[];
239
240
/**
241
* When true, adds the "require" condition.
242
* Otherwise the "import" condition is enabled.
243
* @default false
244
*/
245
require?: boolean;
246
247
/**
248
* Prevents "require", "import", "browser", and/or "node" conditions from being added automatically.
249
* When enabled, only `options.conditions` are added alongside the "default" condition.
250
* @important Enabling this deviates from Node.js default behavior.
251
* @default false
252
*/
253
unsafe?: boolean;
254
}
255
```
256
257
### Package Interface
258
259
Represents a package.json structure for resolution.
260
261
```typescript { .api }
262
interface Package {
263
name: string;
264
version?: string;
265
module?: string;
266
main?: string;
267
imports?: Imports;
268
exports?: Exports;
269
browser?: Browser;
270
[key: string]: any;
271
}
272
```
273
274
### Exports Types
275
276
Export mapping type definitions.
277
278
```typescript { .api }
279
type Exports = Path | {
280
[path: Exports.Entry]: Exports.Value;
281
[cond: Condition]: Exports.Value;
282
};
283
284
namespace Exports {
285
/** Allows "." and "./{name}" */
286
type Entry = `.${string}`;
287
288
/** strings must be internal paths */
289
type Value = Path | null | {
290
[c: Condition]: Value;
291
} | Value[];
292
293
type Output = Path[];
294
}
295
```
296
297
### Imports Types
298
299
Import mapping type definitions.
300
301
```typescript { .api }
302
type Imports = {
303
[entry: Imports.Entry]: Imports.Value;
304
};
305
306
namespace Imports {
307
type Entry = `#${string}`;
308
309
/** External dependency name (not an internal path) */
310
type External = string;
311
312
/** strings are dependency names OR internal paths */
313
type Value = External | Path | null | {
314
[c: Condition]: Value;
315
} | Value[];
316
317
type Output = Array<External | Path>;
318
}
319
```
320
321
### Common Types
322
323
Basic type definitions used throughout the API.
324
325
```typescript { .api }
326
/**
327
* A resolve condition
328
* @example "node", "default", "production"
329
*/
330
type Condition = string;
331
332
/** An internal file path */
333
type Path = `./${string}`;
334
335
type Browser = string[] | string | {
336
[file: Path | string]: string | false;
337
};
338
```
339
340
## Error Handling
341
342
The package throws `Error` instances with specific message formats for resolution failures:
343
344
- `Missing "{entry}" specifier in "{name}" package` - when the requested entry/target is not found in the package's exports/imports
345
- `No known conditions for "{entry}" specifier in "{name}" package` - when no matching conditions are found for the entry
346
347
```typescript
348
try {
349
const result = exports(pkg, "./nonexistent");
350
} catch (error) {
351
console.error(error.message); // Missing "./nonexistent" specifier in "my-package" package
352
}
353
```
354
355
## Advanced Usage
356
357
### Custom Conditions
358
359
```typescript
360
const pkg = {
361
name: "my-package",
362
exports: {
363
".": {
364
"development": "./src/index.js",
365
"production": "./dist/index.js",
366
"default": "./lib/index.js"
367
}
368
}
369
};
370
371
// Resolve with custom condition
372
const devPath = resolve(pkg, ".", {
373
conditions: ["development"],
374
unsafe: true // Only use custom conditions
375
});
376
console.log(devPath); // ["./src/index.js"]
377
```
378
379
### Complex Conditional Exports
380
381
```typescript
382
const pkg = {
383
name: "universal-package",
384
exports: {
385
".": {
386
"import": {
387
"browser": "./dist/browser.mjs",
388
"node": "./dist/node.mjs"
389
},
390
"require": {
391
"browser": "./dist/browser.js",
392
"node": "./dist/node.js"
393
}
394
}
395
}
396
};
397
398
// Browser + ES modules
399
const browserESM = resolve(pkg, ".", { browser: true, require: false });
400
console.log(browserESM); // ["./dist/browser.mjs"]
401
402
// Node.js + CommonJS
403
const nodeCJS = resolve(pkg, ".", { browser: false, require: true });
404
console.log(nodeCJS); // ["./dist/node.js"]
405
```