@rollup/plugin-node-resolve 11.0.1 → 11.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +6 -0
- package/dist/cjs/index.js +331 -136
- package/dist/es/index.js +331 -136
- package/package.json +1 -1
- package/types/index.d.ts +0 -0
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
@@ -42,6 +42,10 @@ export default {
|
|
42
42
|
|
43
43
|
Then call `rollup` either via the [CLI](https://www.rollupjs.org/guide/en/#command-line-reference) or the [API](https://www.rollupjs.org/guide/en/#javascript-api).
|
44
44
|
|
45
|
+
## Package entrypoints
|
46
|
+
|
47
|
+
This plugin supports the package entrypoints feature from node js, specified in the `exports` or `imports` field of a package. Check the [official documentation](https://nodejs.org/api/packages.html#packages_package_entry_points) for more information on how this works.
|
48
|
+
|
45
49
|
## Options
|
46
50
|
|
47
51
|
### `exportConditions`
|
@@ -62,6 +66,8 @@ Default: `false`
|
|
62
66
|
|
63
67
|
If `true`, instructs the plugin to use the `"browser"` property in `package.json` files to specify alternative files to load for bundling. This is useful when bundling for a browser environment. Alternatively, a value of `'browser'` can be added to the `mainFields` option. If `false`, any `"browser"` properties in package files will be ignored. This option takes precedence over `mainFields`.
|
64
68
|
|
69
|
+
> This option does not work when a package is using [package entrypoints](https://nodejs.org/api/packages.html#packages_package_entry_points)
|
70
|
+
|
65
71
|
### `moduleDirectories`
|
66
72
|
|
67
73
|
Type: `Array[...String]`<br>
|
package/dist/cjs/index.js
CHANGED
@@ -8,6 +8,7 @@ var deepMerge = require('deepmerge');
|
|
8
8
|
var isModule = require('is-module');
|
9
9
|
var fs = require('fs');
|
10
10
|
var util = require('util');
|
11
|
+
var url = require('url');
|
11
12
|
var resolve = require('resolve');
|
12
13
|
var pluginutils = require('@rollup/pluginutils');
|
13
14
|
|
@@ -229,168 +230,332 @@ function normalizeInput(input) {
|
|
229
230
|
return [input];
|
230
231
|
}
|
231
232
|
|
232
|
-
|
233
|
-
|
233
|
+
/* eslint-disable no-await-in-loop */
|
234
|
+
|
235
|
+
const fileExists = util.promisify(fs__default['default'].exists);
|
236
|
+
|
237
|
+
function isModuleDir(current, moduleDirs) {
|
238
|
+
return moduleDirs.some((dir) => current.endsWith(dir));
|
239
|
+
}
|
234
240
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
` Package subpath "${subPath}" is not defined by "exports" in ${pkgPath}`
|
239
|
-
);
|
241
|
+
async function findPackageJson(base, moduleDirs) {
|
242
|
+
const { root } = path__default['default'].parse(base);
|
243
|
+
let current = base;
|
240
244
|
|
241
|
-
|
242
|
-
|
243
|
-
|
245
|
+
while (current !== root && !isModuleDir(current, moduleDirs)) {
|
246
|
+
const pkgJsonPath = path__default['default'].join(current, 'package.json');
|
247
|
+
if (await fileExists(pkgJsonPath)) {
|
248
|
+
const pkgJsonString = fs__default['default'].readFileSync(pkgJsonPath, 'utf-8');
|
249
|
+
return { pkgJson: JSON.parse(pkgJsonString), pkgPath: current, pkgJsonPath };
|
250
|
+
}
|
251
|
+
current = path__default['default'].resolve(current, '..');
|
244
252
|
}
|
253
|
+
return null;
|
254
|
+
}
|
245
255
|
|
246
|
-
|
247
|
-
|
248
|
-
|
256
|
+
function isUrl(str) {
|
257
|
+
try {
|
258
|
+
return !!new URL(str);
|
259
|
+
} catch (_) {
|
260
|
+
return false;
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
function isConditions(exports) {
|
265
|
+
return typeof exports === 'object' && Object.keys(exports).every((k) => !k.startsWith('.'));
|
266
|
+
}
|
267
|
+
|
268
|
+
function isMappings(exports) {
|
269
|
+
return typeof exports === 'object' && !isConditions(exports);
|
270
|
+
}
|
271
|
+
|
272
|
+
function isMixedExports(exports) {
|
273
|
+
const keys = Object.keys(exports);
|
274
|
+
return keys.some((k) => k.startsWith('.')) && keys.some((k) => !k.startsWith('.'));
|
275
|
+
}
|
276
|
+
|
277
|
+
function createBaseErrorMsg(importSpecifier, importer) {
|
278
|
+
return `Could not resolve import "${importSpecifier}" in ${importer}`;
|
279
|
+
}
|
280
|
+
|
281
|
+
function createErrorMsg(context, reason, internal) {
|
282
|
+
const { importSpecifier, importer, pkgJsonPath } = context;
|
283
|
+
const base = createBaseErrorMsg(importSpecifier, importer);
|
284
|
+
const field = internal ? 'imports' : 'exports';
|
285
|
+
return `${base} using ${field} defined in ${pkgJsonPath}.${reason ? ` ${reason}` : ''}`;
|
286
|
+
}
|
287
|
+
|
288
|
+
class ResolveError extends Error {}
|
289
|
+
|
290
|
+
class InvalidConfigurationError extends ResolveError {
|
291
|
+
constructor(context, reason) {
|
292
|
+
super(createErrorMsg(context, `Invalid "exports" field. ${reason}`));
|
293
|
+
}
|
294
|
+
}
|
295
|
+
|
296
|
+
class InvalidModuleSpecifierError extends ResolveError {
|
297
|
+
constructor(context, internal) {
|
298
|
+
super(createErrorMsg(context, internal));
|
299
|
+
}
|
300
|
+
}
|
249
301
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
302
|
+
class InvalidPackageTargetError extends ResolveError {
|
303
|
+
constructor(context, reason) {
|
304
|
+
super(createErrorMsg(context, reason));
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
308
|
+
/* eslint-disable no-await-in-loop, no-undefined */
|
309
|
+
|
310
|
+
function includesInvalidSegments(pathSegments, moduleDirs) {
|
311
|
+
return pathSegments
|
312
|
+
.split('/')
|
313
|
+
.slice(1)
|
314
|
+
.some((t) => ['.', '..', ...moduleDirs].includes(t));
|
315
|
+
}
|
316
|
+
|
317
|
+
async function resolvePackageTarget(context, { target, subpath, pattern, internal }) {
|
318
|
+
if (typeof target === 'string') {
|
319
|
+
if (!pattern && subpath.length > 0 && !target.endsWith('/')) {
|
320
|
+
throw new InvalidModuleSpecifierError(context);
|
321
|
+
}
|
322
|
+
|
323
|
+
if (!target.startsWith('./')) {
|
324
|
+
if (internal && !['/', '../'].some((p) => target.startsWith(p)) && !isUrl(target)) {
|
325
|
+
// this is a bare package import, remap it and resolve it using regular node resolve
|
326
|
+
if (pattern) {
|
327
|
+
const result = await context.resolveId(
|
328
|
+
target.replace(/\*/g, subpath),
|
329
|
+
context.pkgURL.href
|
330
|
+
);
|
331
|
+
return result ? url.pathToFileURL(result.location) : null;
|
332
|
+
}
|
333
|
+
|
334
|
+
const result = await context.resolveId(`${target}${subpath}`, context.pkgURL.href);
|
335
|
+
return result ? url.pathToFileURL(result.location) : null;
|
256
336
|
}
|
337
|
+
throw new InvalidPackageTargetError(context, `Invalid mapping: "${target}".`);
|
338
|
+
}
|
339
|
+
|
340
|
+
if (includesInvalidSegments(target, context.moduleDirs)) {
|
341
|
+
throw new InvalidPackageTargetError(context, `Invalid mapping: "${target}".`);
|
342
|
+
}
|
343
|
+
|
344
|
+
const resolvedTarget = new URL(target, context.pkgURL);
|
345
|
+
if (!resolvedTarget.href.startsWith(context.pkgURL.href)) {
|
346
|
+
throw new InvalidPackageTargetError(
|
347
|
+
context,
|
348
|
+
`Resolved to ${resolvedTarget.href} which is outside package ${context.pkgURL.href}`
|
349
|
+
);
|
257
350
|
}
|
258
351
|
|
259
|
-
if (
|
260
|
-
|
261
|
-
return key;
|
352
|
+
if (includesInvalidSegments(subpath, context.moduleDirs)) {
|
353
|
+
throw new InvalidModuleSpecifierError(context);
|
262
354
|
}
|
263
355
|
|
264
|
-
if (
|
265
|
-
|
266
|
-
return key;
|
356
|
+
if (pattern) {
|
357
|
+
return resolvedTarget.href.replace(/\*/g, subpath);
|
267
358
|
}
|
359
|
+
return new URL(subpath, resolvedTarget).href;
|
268
360
|
}
|
269
|
-
return null;
|
270
|
-
}
|
271
361
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
362
|
+
if (Array.isArray(target)) {
|
363
|
+
let lastError;
|
364
|
+
for (const item of target) {
|
365
|
+
try {
|
366
|
+
const resolved = await resolvePackageTarget(context, {
|
367
|
+
target: item,
|
368
|
+
subpath,
|
369
|
+
pattern,
|
370
|
+
internal
|
371
|
+
});
|
372
|
+
|
373
|
+
// return if defined or null, but not undefined
|
374
|
+
if (resolved !== undefined) {
|
375
|
+
return resolved;
|
376
|
+
}
|
377
|
+
} catch (error) {
|
378
|
+
if (!(error instanceof InvalidPackageTargetError)) {
|
379
|
+
throw error;
|
380
|
+
} else {
|
381
|
+
lastError = error;
|
382
|
+
}
|
383
|
+
}
|
279
384
|
}
|
280
385
|
|
281
|
-
if (
|
282
|
-
|
283
|
-
return `${value}${subPath.substring(key.length)}`;
|
386
|
+
if (lastError) {
|
387
|
+
throw lastError;
|
284
388
|
}
|
389
|
+
return null;
|
390
|
+
}
|
285
391
|
|
286
|
-
|
287
|
-
|
392
|
+
if (target && typeof target === 'object') {
|
393
|
+
for (const [key, value] of Object.entries(target)) {
|
394
|
+
if (key === 'default' || context.conditions.includes(key)) {
|
395
|
+
const resolved = await resolvePackageTarget(context, {
|
396
|
+
target: value,
|
397
|
+
subpath,
|
398
|
+
pattern,
|
399
|
+
internal
|
400
|
+
});
|
401
|
+
|
402
|
+
// return if defined or null, but not undefined
|
403
|
+
if (resolved !== undefined) {
|
404
|
+
return resolved;
|
405
|
+
}
|
406
|
+
}
|
407
|
+
}
|
408
|
+
return undefined;
|
288
409
|
}
|
289
410
|
|
290
|
-
if (
|
291
|
-
|
292
|
-
return value.find((v) => v.startsWith('./'));
|
411
|
+
if (target === null) {
|
412
|
+
return null;
|
293
413
|
}
|
294
414
|
|
295
|
-
throw
|
415
|
+
throw new InvalidPackageTargetError(context, `Invalid exports field.`);
|
296
416
|
}
|
297
417
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
key
|
306
|
-
}) {
|
307
|
-
if (typeof exportMap !== 'object') {
|
308
|
-
return mapSubPath({ importPath, importer, pkgJsonPath, subPath, key, value: exportMap });
|
418
|
+
/* eslint-disable no-await-in-loop */
|
419
|
+
|
420
|
+
async function resolvePackageImportsExports(context, { matchKey, matchObj, internal }) {
|
421
|
+
if (!matchKey.endsWith('*') && matchKey in matchObj) {
|
422
|
+
const target = matchObj[matchKey];
|
423
|
+
const resolved = await resolvePackageTarget(context, { target, subpath: '', internal });
|
424
|
+
return resolved;
|
309
425
|
}
|
310
426
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
427
|
+
const expansionKeys = Object.keys(matchObj)
|
428
|
+
.filter((k) => k.endsWith('/') || k.endsWith('*'))
|
429
|
+
.sort((a, b) => b.length - a.length);
|
430
|
+
|
431
|
+
for (const expansionKey of expansionKeys) {
|
432
|
+
const prefix = expansionKey.substring(0, expansionKey.length - 1);
|
433
|
+
|
434
|
+
if (expansionKey.endsWith('*') && matchKey.startsWith(prefix)) {
|
435
|
+
const target = matchObj[expansionKey];
|
436
|
+
const subpath = matchKey.substring(expansionKey.length - 1);
|
437
|
+
const resolved = await resolvePackageTarget(context, {
|
438
|
+
target,
|
439
|
+
subpath,
|
440
|
+
pattern: true,
|
441
|
+
internal
|
322
442
|
});
|
323
|
-
|
324
|
-
return mappedSubPath;
|
325
|
-
}
|
443
|
+
return resolved;
|
326
444
|
}
|
327
|
-
}
|
328
|
-
throw pathNotFoundError(importer, subPath, pkgJsonPath);
|
329
|
-
}
|
330
445
|
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
conditions
|
338
|
-
}) {
|
339
|
-
if (typeof exportMap !== 'object') {
|
340
|
-
// the export map shorthand, for example { exports: "./index.js" }
|
341
|
-
if (subPath !== '.') {
|
342
|
-
// shorthand only supports a main entrypoint
|
343
|
-
throw pathNotFoundError(importPath, importer, subPath, pkgJsonPath);
|
446
|
+
if (matchKey.startsWith(expansionKey)) {
|
447
|
+
const target = matchObj[expansionKey];
|
448
|
+
const subpath = matchKey.substring(expansionKey.length);
|
449
|
+
|
450
|
+
const resolved = await resolvePackageTarget(context, { target, subpath, internal });
|
451
|
+
return resolved;
|
344
452
|
}
|
345
|
-
return mapSubPath({ importPath, importer, pkgJsonPath, subPath, key: null, value: exportMap });
|
346
453
|
}
|
347
454
|
|
348
|
-
|
349
|
-
|
350
|
-
const isConditions = keys.every((k) => !k.startsWith('.'));
|
351
|
-
const isMappings = keys.every((k) => k.startsWith('.'));
|
455
|
+
throw new InvalidModuleSpecifierError(context, internal);
|
456
|
+
}
|
352
457
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
458
|
+
async function resolvePackageExports(context, subpath, exports) {
|
459
|
+
if (isMixedExports(exports)) {
|
460
|
+
throw new InvalidConfigurationError(
|
461
|
+
context,
|
462
|
+
'All keys must either start with ./, or without one.'
|
358
463
|
);
|
359
464
|
}
|
360
465
|
|
361
|
-
|
362
|
-
|
466
|
+
if (subpath === '.') {
|
467
|
+
let mainExport;
|
468
|
+
// If exports is a String or Array, or an Object containing no keys starting with ".", then
|
469
|
+
if (typeof exports === 'string' || Array.isArray(exports) || isConditions(exports)) {
|
470
|
+
mainExport = exports;
|
471
|
+
} else if (isMappings(exports)) {
|
472
|
+
mainExport = exports['.'];
|
473
|
+
}
|
363
474
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
475
|
+
if (mainExport) {
|
476
|
+
const resolved = await resolvePackageTarget(context, { target: mainExport, subpath: '' });
|
477
|
+
if (resolved) {
|
478
|
+
return resolved;
|
479
|
+
}
|
369
480
|
}
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
481
|
+
} else if (isMappings(exports)) {
|
482
|
+
const resolvedMatch = await resolvePackageImportsExports(context, {
|
483
|
+
matchKey: subpath,
|
484
|
+
matchObj: exports
|
485
|
+
});
|
486
|
+
|
487
|
+
if (resolvedMatch) {
|
488
|
+
return resolvedMatch;
|
376
489
|
}
|
377
|
-
exportMapForSubPath = exportMap[key];
|
378
490
|
}
|
379
491
|
|
380
|
-
|
381
|
-
|
492
|
+
throw new InvalidModuleSpecifierError(context);
|
493
|
+
}
|
494
|
+
|
495
|
+
async function resolvePackageImports({
|
496
|
+
importSpecifier,
|
497
|
+
importer,
|
498
|
+
moduleDirs,
|
499
|
+
conditions,
|
500
|
+
resolveId
|
501
|
+
}) {
|
502
|
+
const result = await findPackageJson(importer, moduleDirs);
|
503
|
+
if (!result) {
|
504
|
+
throw new Error(createBaseErrorMsg('. Could not find a parent package.json.'));
|
505
|
+
}
|
506
|
+
|
507
|
+
const { pkgPath, pkgJsonPath, pkgJson } = result;
|
508
|
+
const pkgURL = url.pathToFileURL(`${pkgPath}/`);
|
509
|
+
const context = {
|
382
510
|
importer,
|
511
|
+
importSpecifier,
|
512
|
+
moduleDirs,
|
513
|
+
pkgURL,
|
383
514
|
pkgJsonPath,
|
384
|
-
subPath,
|
385
|
-
exportMap: exportMapForSubPath,
|
386
515
|
conditions,
|
387
|
-
|
516
|
+
resolveId
|
517
|
+
};
|
518
|
+
|
519
|
+
const { imports } = pkgJson;
|
520
|
+
if (!imports) {
|
521
|
+
throw new InvalidModuleSpecifierError(context, true);
|
522
|
+
}
|
523
|
+
|
524
|
+
if (importSpecifier === '#' || importSpecifier.startsWith('#/')) {
|
525
|
+
throw new InvalidModuleSpecifierError(context, 'Invalid import specifier.');
|
526
|
+
}
|
527
|
+
|
528
|
+
return resolvePackageImportsExports(context, {
|
529
|
+
matchKey: importSpecifier,
|
530
|
+
matchObj: imports,
|
531
|
+
internal: true
|
388
532
|
});
|
389
533
|
}
|
390
534
|
|
535
|
+
const resolveImportPath = util.promisify(resolve__default['default']);
|
536
|
+
const readFile$1 = util.promisify(fs__default['default'].readFile);
|
537
|
+
|
538
|
+
async function getPackageJson(importer, pkgName, resolveOptions, moduleDirectories) {
|
539
|
+
if (importer) {
|
540
|
+
const selfPackageJsonResult = await findPackageJson(importer, moduleDirectories);
|
541
|
+
if (selfPackageJsonResult && selfPackageJsonResult.pkgJson.name === pkgName) {
|
542
|
+
// the referenced package name is the current package
|
543
|
+
return selfPackageJsonResult;
|
544
|
+
}
|
545
|
+
}
|
546
|
+
|
547
|
+
try {
|
548
|
+
const pkgJsonPath = await resolveImportPath(`${pkgName}/package.json`, resolveOptions);
|
549
|
+
const pkgJson = JSON.parse(await readFile$1(pkgJsonPath, 'utf-8'));
|
550
|
+
return { pkgJsonPath, pkgJson };
|
551
|
+
} catch (_) {
|
552
|
+
return null;
|
553
|
+
}
|
554
|
+
}
|
555
|
+
|
391
556
|
async function resolveId({
|
392
557
|
importer,
|
393
|
-
|
558
|
+
importSpecifier,
|
394
559
|
exportConditions,
|
395
560
|
warn,
|
396
561
|
packageInfoCache,
|
@@ -436,32 +601,61 @@ async function resolveId({
|
|
436
601
|
|
437
602
|
let location;
|
438
603
|
|
439
|
-
const pkgName = getPackageName(
|
440
|
-
if (
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
604
|
+
const pkgName = getPackageName(importSpecifier);
|
605
|
+
if (importSpecifier.startsWith('#')) {
|
606
|
+
// this is a package internal import, resolve using package imports field
|
607
|
+
const resolveResult = await resolvePackageImports({
|
608
|
+
importSpecifier,
|
609
|
+
importer,
|
610
|
+
moduleDirs: moduleDirectories,
|
611
|
+
conditions: exportConditions,
|
612
|
+
resolveId(id, parent) {
|
613
|
+
return resolveId({
|
614
|
+
importSpecifier: id,
|
615
|
+
importer: parent,
|
616
|
+
exportConditions,
|
617
|
+
warn,
|
618
|
+
packageInfoCache,
|
619
|
+
extensions,
|
620
|
+
mainFields,
|
621
|
+
preserveSymlinks,
|
622
|
+
useBrowserOverrides,
|
623
|
+
baseDir,
|
624
|
+
moduleDirectories
|
625
|
+
});
|
626
|
+
}
|
627
|
+
});
|
628
|
+
location = url.fileURLToPath(resolveResult);
|
629
|
+
} else if (pkgName) {
|
630
|
+
// it's a bare import, find the package.json and resolve using package exports if available
|
631
|
+
const result = await getPackageJson(importer, pkgName, resolveOptions, moduleDirectories);
|
449
632
|
|
450
|
-
if (
|
633
|
+
if (result && result.pkgJson.exports) {
|
634
|
+
const { pkgJson, pkgJsonPath } = result;
|
451
635
|
try {
|
452
|
-
const
|
453
|
-
pkgName ===
|
454
|
-
const
|
636
|
+
const subpath =
|
637
|
+
pkgName === importSpecifier ? '.' : `.${importSpecifier.substring(pkgName.length)}`;
|
638
|
+
const pkgDr = pkgJsonPath.replace('package.json', '');
|
639
|
+
const pkgURL = url.pathToFileURL(pkgDr);
|
640
|
+
|
641
|
+
const context = {
|
455
642
|
importer,
|
456
|
-
|
643
|
+
importSpecifier,
|
644
|
+
moduleDirs: moduleDirectories,
|
645
|
+
pkgURL,
|
457
646
|
pkgJsonPath,
|
458
|
-
subPath: packageSubPath,
|
459
|
-
exportMap: pkgJson.exports,
|
460
647
|
conditions: exportConditions
|
461
|
-
}
|
462
|
-
const
|
463
|
-
|
648
|
+
};
|
649
|
+
const resolvedPackageExport = await resolvePackageExports(
|
650
|
+
context,
|
651
|
+
subpath,
|
652
|
+
pkgJson.exports
|
653
|
+
);
|
654
|
+
location = url.fileURLToPath(resolvedPackageExport);
|
464
655
|
} catch (error) {
|
656
|
+
if (!(error instanceof ResolveError)) {
|
657
|
+
throw error;
|
658
|
+
}
|
465
659
|
warn(error);
|
466
660
|
return null;
|
467
661
|
}
|
@@ -469,8 +663,9 @@ async function resolveId({
|
|
469
663
|
}
|
470
664
|
|
471
665
|
if (!location) {
|
666
|
+
// package has no imports or exports, use classic node resolve
|
472
667
|
try {
|
473
|
-
location = await resolveImportPath(
|
668
|
+
location = await resolveImportPath(importSpecifier, resolveOptions);
|
474
669
|
} catch (error) {
|
475
670
|
if (error.code !== 'MODULE_NOT_FOUND') {
|
476
671
|
throw error;
|
@@ -513,7 +708,7 @@ async function resolveImportSpecifiers({
|
|
513
708
|
// eslint-disable-next-line no-await-in-loop
|
514
709
|
const resolved = await resolveId({
|
515
710
|
importer,
|
516
|
-
|
711
|
+
importSpecifier: importSpecifierList[i],
|
517
712
|
exportConditions,
|
518
713
|
warn,
|
519
714
|
packageInfoCache,
|
package/dist/es/index.js
CHANGED
@@ -4,6 +4,7 @@ import deepMerge from 'deepmerge';
|
|
4
4
|
import isModule from 'is-module';
|
5
5
|
import fs, { realpathSync } from 'fs';
|
6
6
|
import { promisify } from 'util';
|
7
|
+
import { pathToFileURL, fileURLToPath } from 'url';
|
7
8
|
import resolve$1 from 'resolve';
|
8
9
|
import { createFilter } from '@rollup/pluginutils';
|
9
10
|
|
@@ -216,168 +217,332 @@ function normalizeInput(input) {
|
|
216
217
|
return [input];
|
217
218
|
}
|
218
219
|
|
219
|
-
|
220
|
-
|
220
|
+
/* eslint-disable no-await-in-loop */
|
221
|
+
|
222
|
+
const fileExists = promisify(fs.exists);
|
223
|
+
|
224
|
+
function isModuleDir(current, moduleDirs) {
|
225
|
+
return moduleDirs.some((dir) => current.endsWith(dir));
|
226
|
+
}
|
221
227
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
` Package subpath "${subPath}" is not defined by "exports" in ${pkgPath}`
|
226
|
-
);
|
228
|
+
async function findPackageJson(base, moduleDirs) {
|
229
|
+
const { root } = path.parse(base);
|
230
|
+
let current = base;
|
227
231
|
|
228
|
-
|
229
|
-
|
230
|
-
|
232
|
+
while (current !== root && !isModuleDir(current, moduleDirs)) {
|
233
|
+
const pkgJsonPath = path.join(current, 'package.json');
|
234
|
+
if (await fileExists(pkgJsonPath)) {
|
235
|
+
const pkgJsonString = fs.readFileSync(pkgJsonPath, 'utf-8');
|
236
|
+
return { pkgJson: JSON.parse(pkgJsonString), pkgPath: current, pkgJsonPath };
|
237
|
+
}
|
238
|
+
current = path.resolve(current, '..');
|
231
239
|
}
|
240
|
+
return null;
|
241
|
+
}
|
232
242
|
|
233
|
-
|
234
|
-
|
235
|
-
|
243
|
+
function isUrl(str) {
|
244
|
+
try {
|
245
|
+
return !!new URL(str);
|
246
|
+
} catch (_) {
|
247
|
+
return false;
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
251
|
+
function isConditions(exports) {
|
252
|
+
return typeof exports === 'object' && Object.keys(exports).every((k) => !k.startsWith('.'));
|
253
|
+
}
|
254
|
+
|
255
|
+
function isMappings(exports) {
|
256
|
+
return typeof exports === 'object' && !isConditions(exports);
|
257
|
+
}
|
258
|
+
|
259
|
+
function isMixedExports(exports) {
|
260
|
+
const keys = Object.keys(exports);
|
261
|
+
return keys.some((k) => k.startsWith('.')) && keys.some((k) => !k.startsWith('.'));
|
262
|
+
}
|
263
|
+
|
264
|
+
function createBaseErrorMsg(importSpecifier, importer) {
|
265
|
+
return `Could not resolve import "${importSpecifier}" in ${importer}`;
|
266
|
+
}
|
267
|
+
|
268
|
+
function createErrorMsg(context, reason, internal) {
|
269
|
+
const { importSpecifier, importer, pkgJsonPath } = context;
|
270
|
+
const base = createBaseErrorMsg(importSpecifier, importer);
|
271
|
+
const field = internal ? 'imports' : 'exports';
|
272
|
+
return `${base} using ${field} defined in ${pkgJsonPath}.${reason ? ` ${reason}` : ''}`;
|
273
|
+
}
|
274
|
+
|
275
|
+
class ResolveError extends Error {}
|
276
|
+
|
277
|
+
class InvalidConfigurationError extends ResolveError {
|
278
|
+
constructor(context, reason) {
|
279
|
+
super(createErrorMsg(context, `Invalid "exports" field. ${reason}`));
|
280
|
+
}
|
281
|
+
}
|
282
|
+
|
283
|
+
class InvalidModuleSpecifierError extends ResolveError {
|
284
|
+
constructor(context, internal) {
|
285
|
+
super(createErrorMsg(context, internal));
|
286
|
+
}
|
287
|
+
}
|
236
288
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
289
|
+
class InvalidPackageTargetError extends ResolveError {
|
290
|
+
constructor(context, reason) {
|
291
|
+
super(createErrorMsg(context, reason));
|
292
|
+
}
|
293
|
+
}
|
294
|
+
|
295
|
+
/* eslint-disable no-await-in-loop, no-undefined */
|
296
|
+
|
297
|
+
function includesInvalidSegments(pathSegments, moduleDirs) {
|
298
|
+
return pathSegments
|
299
|
+
.split('/')
|
300
|
+
.slice(1)
|
301
|
+
.some((t) => ['.', '..', ...moduleDirs].includes(t));
|
302
|
+
}
|
303
|
+
|
304
|
+
async function resolvePackageTarget(context, { target, subpath, pattern, internal }) {
|
305
|
+
if (typeof target === 'string') {
|
306
|
+
if (!pattern && subpath.length > 0 && !target.endsWith('/')) {
|
307
|
+
throw new InvalidModuleSpecifierError(context);
|
308
|
+
}
|
309
|
+
|
310
|
+
if (!target.startsWith('./')) {
|
311
|
+
if (internal && !['/', '../'].some((p) => target.startsWith(p)) && !isUrl(target)) {
|
312
|
+
// this is a bare package import, remap it and resolve it using regular node resolve
|
313
|
+
if (pattern) {
|
314
|
+
const result = await context.resolveId(
|
315
|
+
target.replace(/\*/g, subpath),
|
316
|
+
context.pkgURL.href
|
317
|
+
);
|
318
|
+
return result ? pathToFileURL(result.location) : null;
|
319
|
+
}
|
320
|
+
|
321
|
+
const result = await context.resolveId(`${target}${subpath}`, context.pkgURL.href);
|
322
|
+
return result ? pathToFileURL(result.location) : null;
|
243
323
|
}
|
324
|
+
throw new InvalidPackageTargetError(context, `Invalid mapping: "${target}".`);
|
325
|
+
}
|
326
|
+
|
327
|
+
if (includesInvalidSegments(target, context.moduleDirs)) {
|
328
|
+
throw new InvalidPackageTargetError(context, `Invalid mapping: "${target}".`);
|
329
|
+
}
|
330
|
+
|
331
|
+
const resolvedTarget = new URL(target, context.pkgURL);
|
332
|
+
if (!resolvedTarget.href.startsWith(context.pkgURL.href)) {
|
333
|
+
throw new InvalidPackageTargetError(
|
334
|
+
context,
|
335
|
+
`Resolved to ${resolvedTarget.href} which is outside package ${context.pkgURL.href}`
|
336
|
+
);
|
244
337
|
}
|
245
338
|
|
246
|
-
if (
|
247
|
-
|
248
|
-
return key;
|
339
|
+
if (includesInvalidSegments(subpath, context.moduleDirs)) {
|
340
|
+
throw new InvalidModuleSpecifierError(context);
|
249
341
|
}
|
250
342
|
|
251
|
-
if (
|
252
|
-
|
253
|
-
return key;
|
343
|
+
if (pattern) {
|
344
|
+
return resolvedTarget.href.replace(/\*/g, subpath);
|
254
345
|
}
|
346
|
+
return new URL(subpath, resolvedTarget).href;
|
255
347
|
}
|
256
|
-
return null;
|
257
|
-
}
|
258
348
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
349
|
+
if (Array.isArray(target)) {
|
350
|
+
let lastError;
|
351
|
+
for (const item of target) {
|
352
|
+
try {
|
353
|
+
const resolved = await resolvePackageTarget(context, {
|
354
|
+
target: item,
|
355
|
+
subpath,
|
356
|
+
pattern,
|
357
|
+
internal
|
358
|
+
});
|
359
|
+
|
360
|
+
// return if defined or null, but not undefined
|
361
|
+
if (resolved !== undefined) {
|
362
|
+
return resolved;
|
363
|
+
}
|
364
|
+
} catch (error) {
|
365
|
+
if (!(error instanceof InvalidPackageTargetError)) {
|
366
|
+
throw error;
|
367
|
+
} else {
|
368
|
+
lastError = error;
|
369
|
+
}
|
370
|
+
}
|
266
371
|
}
|
267
372
|
|
268
|
-
if (
|
269
|
-
|
270
|
-
return `${value}${subPath.substring(key.length)}`;
|
373
|
+
if (lastError) {
|
374
|
+
throw lastError;
|
271
375
|
}
|
376
|
+
return null;
|
377
|
+
}
|
272
378
|
|
273
|
-
|
274
|
-
|
379
|
+
if (target && typeof target === 'object') {
|
380
|
+
for (const [key, value] of Object.entries(target)) {
|
381
|
+
if (key === 'default' || context.conditions.includes(key)) {
|
382
|
+
const resolved = await resolvePackageTarget(context, {
|
383
|
+
target: value,
|
384
|
+
subpath,
|
385
|
+
pattern,
|
386
|
+
internal
|
387
|
+
});
|
388
|
+
|
389
|
+
// return if defined or null, but not undefined
|
390
|
+
if (resolved !== undefined) {
|
391
|
+
return resolved;
|
392
|
+
}
|
393
|
+
}
|
394
|
+
}
|
395
|
+
return undefined;
|
275
396
|
}
|
276
397
|
|
277
|
-
if (
|
278
|
-
|
279
|
-
return value.find((v) => v.startsWith('./'));
|
398
|
+
if (target === null) {
|
399
|
+
return null;
|
280
400
|
}
|
281
401
|
|
282
|
-
throw
|
402
|
+
throw new InvalidPackageTargetError(context, `Invalid exports field.`);
|
283
403
|
}
|
284
404
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
key
|
293
|
-
}) {
|
294
|
-
if (typeof exportMap !== 'object') {
|
295
|
-
return mapSubPath({ importPath, importer, pkgJsonPath, subPath, key, value: exportMap });
|
405
|
+
/* eslint-disable no-await-in-loop */
|
406
|
+
|
407
|
+
async function resolvePackageImportsExports(context, { matchKey, matchObj, internal }) {
|
408
|
+
if (!matchKey.endsWith('*') && matchKey in matchObj) {
|
409
|
+
const target = matchObj[matchKey];
|
410
|
+
const resolved = await resolvePackageTarget(context, { target, subpath: '', internal });
|
411
|
+
return resolved;
|
296
412
|
}
|
297
413
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
414
|
+
const expansionKeys = Object.keys(matchObj)
|
415
|
+
.filter((k) => k.endsWith('/') || k.endsWith('*'))
|
416
|
+
.sort((a, b) => b.length - a.length);
|
417
|
+
|
418
|
+
for (const expansionKey of expansionKeys) {
|
419
|
+
const prefix = expansionKey.substring(0, expansionKey.length - 1);
|
420
|
+
|
421
|
+
if (expansionKey.endsWith('*') && matchKey.startsWith(prefix)) {
|
422
|
+
const target = matchObj[expansionKey];
|
423
|
+
const subpath = matchKey.substring(expansionKey.length - 1);
|
424
|
+
const resolved = await resolvePackageTarget(context, {
|
425
|
+
target,
|
426
|
+
subpath,
|
427
|
+
pattern: true,
|
428
|
+
internal
|
309
429
|
});
|
310
|
-
|
311
|
-
return mappedSubPath;
|
312
|
-
}
|
430
|
+
return resolved;
|
313
431
|
}
|
314
|
-
}
|
315
|
-
throw pathNotFoundError(importer, subPath, pkgJsonPath);
|
316
|
-
}
|
317
432
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
conditions
|
325
|
-
}) {
|
326
|
-
if (typeof exportMap !== 'object') {
|
327
|
-
// the export map shorthand, for example { exports: "./index.js" }
|
328
|
-
if (subPath !== '.') {
|
329
|
-
// shorthand only supports a main entrypoint
|
330
|
-
throw pathNotFoundError(importPath, importer, subPath, pkgJsonPath);
|
433
|
+
if (matchKey.startsWith(expansionKey)) {
|
434
|
+
const target = matchObj[expansionKey];
|
435
|
+
const subpath = matchKey.substring(expansionKey.length);
|
436
|
+
|
437
|
+
const resolved = await resolvePackageTarget(context, { target, subpath, internal });
|
438
|
+
return resolved;
|
331
439
|
}
|
332
|
-
return mapSubPath({ importPath, importer, pkgJsonPath, subPath, key: null, value: exportMap });
|
333
440
|
}
|
334
441
|
|
335
|
-
|
336
|
-
|
337
|
-
const isConditions = keys.every((k) => !k.startsWith('.'));
|
338
|
-
const isMappings = keys.every((k) => k.startsWith('.'));
|
442
|
+
throw new InvalidModuleSpecifierError(context, internal);
|
443
|
+
}
|
339
444
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
445
|
+
async function resolvePackageExports(context, subpath, exports) {
|
446
|
+
if (isMixedExports(exports)) {
|
447
|
+
throw new InvalidConfigurationError(
|
448
|
+
context,
|
449
|
+
'All keys must either start with ./, or without one.'
|
345
450
|
);
|
346
451
|
}
|
347
452
|
|
348
|
-
|
349
|
-
|
453
|
+
if (subpath === '.') {
|
454
|
+
let mainExport;
|
455
|
+
// If exports is a String or Array, or an Object containing no keys starting with ".", then
|
456
|
+
if (typeof exports === 'string' || Array.isArray(exports) || isConditions(exports)) {
|
457
|
+
mainExport = exports;
|
458
|
+
} else if (isMappings(exports)) {
|
459
|
+
mainExport = exports['.'];
|
460
|
+
}
|
350
461
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
462
|
+
if (mainExport) {
|
463
|
+
const resolved = await resolvePackageTarget(context, { target: mainExport, subpath: '' });
|
464
|
+
if (resolved) {
|
465
|
+
return resolved;
|
466
|
+
}
|
356
467
|
}
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
468
|
+
} else if (isMappings(exports)) {
|
469
|
+
const resolvedMatch = await resolvePackageImportsExports(context, {
|
470
|
+
matchKey: subpath,
|
471
|
+
matchObj: exports
|
472
|
+
});
|
473
|
+
|
474
|
+
if (resolvedMatch) {
|
475
|
+
return resolvedMatch;
|
363
476
|
}
|
364
|
-
exportMapForSubPath = exportMap[key];
|
365
477
|
}
|
366
478
|
|
367
|
-
|
368
|
-
|
479
|
+
throw new InvalidModuleSpecifierError(context);
|
480
|
+
}
|
481
|
+
|
482
|
+
async function resolvePackageImports({
|
483
|
+
importSpecifier,
|
484
|
+
importer,
|
485
|
+
moduleDirs,
|
486
|
+
conditions,
|
487
|
+
resolveId
|
488
|
+
}) {
|
489
|
+
const result = await findPackageJson(importer, moduleDirs);
|
490
|
+
if (!result) {
|
491
|
+
throw new Error(createBaseErrorMsg('. Could not find a parent package.json.'));
|
492
|
+
}
|
493
|
+
|
494
|
+
const { pkgPath, pkgJsonPath, pkgJson } = result;
|
495
|
+
const pkgURL = pathToFileURL(`${pkgPath}/`);
|
496
|
+
const context = {
|
369
497
|
importer,
|
498
|
+
importSpecifier,
|
499
|
+
moduleDirs,
|
500
|
+
pkgURL,
|
370
501
|
pkgJsonPath,
|
371
|
-
subPath,
|
372
|
-
exportMap: exportMapForSubPath,
|
373
502
|
conditions,
|
374
|
-
|
503
|
+
resolveId
|
504
|
+
};
|
505
|
+
|
506
|
+
const { imports } = pkgJson;
|
507
|
+
if (!imports) {
|
508
|
+
throw new InvalidModuleSpecifierError(context, true);
|
509
|
+
}
|
510
|
+
|
511
|
+
if (importSpecifier === '#' || importSpecifier.startsWith('#/')) {
|
512
|
+
throw new InvalidModuleSpecifierError(context, 'Invalid import specifier.');
|
513
|
+
}
|
514
|
+
|
515
|
+
return resolvePackageImportsExports(context, {
|
516
|
+
matchKey: importSpecifier,
|
517
|
+
matchObj: imports,
|
518
|
+
internal: true
|
375
519
|
});
|
376
520
|
}
|
377
521
|
|
522
|
+
const resolveImportPath = promisify(resolve$1);
|
523
|
+
const readFile$1 = promisify(fs.readFile);
|
524
|
+
|
525
|
+
async function getPackageJson(importer, pkgName, resolveOptions, moduleDirectories) {
|
526
|
+
if (importer) {
|
527
|
+
const selfPackageJsonResult = await findPackageJson(importer, moduleDirectories);
|
528
|
+
if (selfPackageJsonResult && selfPackageJsonResult.pkgJson.name === pkgName) {
|
529
|
+
// the referenced package name is the current package
|
530
|
+
return selfPackageJsonResult;
|
531
|
+
}
|
532
|
+
}
|
533
|
+
|
534
|
+
try {
|
535
|
+
const pkgJsonPath = await resolveImportPath(`${pkgName}/package.json`, resolveOptions);
|
536
|
+
const pkgJson = JSON.parse(await readFile$1(pkgJsonPath, 'utf-8'));
|
537
|
+
return { pkgJsonPath, pkgJson };
|
538
|
+
} catch (_) {
|
539
|
+
return null;
|
540
|
+
}
|
541
|
+
}
|
542
|
+
|
378
543
|
async function resolveId({
|
379
544
|
importer,
|
380
|
-
|
545
|
+
importSpecifier,
|
381
546
|
exportConditions,
|
382
547
|
warn,
|
383
548
|
packageInfoCache,
|
@@ -423,32 +588,61 @@ async function resolveId({
|
|
423
588
|
|
424
589
|
let location;
|
425
590
|
|
426
|
-
const pkgName = getPackageName(
|
427
|
-
if (
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
591
|
+
const pkgName = getPackageName(importSpecifier);
|
592
|
+
if (importSpecifier.startsWith('#')) {
|
593
|
+
// this is a package internal import, resolve using package imports field
|
594
|
+
const resolveResult = await resolvePackageImports({
|
595
|
+
importSpecifier,
|
596
|
+
importer,
|
597
|
+
moduleDirs: moduleDirectories,
|
598
|
+
conditions: exportConditions,
|
599
|
+
resolveId(id, parent) {
|
600
|
+
return resolveId({
|
601
|
+
importSpecifier: id,
|
602
|
+
importer: parent,
|
603
|
+
exportConditions,
|
604
|
+
warn,
|
605
|
+
packageInfoCache,
|
606
|
+
extensions,
|
607
|
+
mainFields,
|
608
|
+
preserveSymlinks,
|
609
|
+
useBrowserOverrides,
|
610
|
+
baseDir,
|
611
|
+
moduleDirectories
|
612
|
+
});
|
613
|
+
}
|
614
|
+
});
|
615
|
+
location = fileURLToPath(resolveResult);
|
616
|
+
} else if (pkgName) {
|
617
|
+
// it's a bare import, find the package.json and resolve using package exports if available
|
618
|
+
const result = await getPackageJson(importer, pkgName, resolveOptions, moduleDirectories);
|
436
619
|
|
437
|
-
if (
|
620
|
+
if (result && result.pkgJson.exports) {
|
621
|
+
const { pkgJson, pkgJsonPath } = result;
|
438
622
|
try {
|
439
|
-
const
|
440
|
-
pkgName ===
|
441
|
-
const
|
623
|
+
const subpath =
|
624
|
+
pkgName === importSpecifier ? '.' : `.${importSpecifier.substring(pkgName.length)}`;
|
625
|
+
const pkgDr = pkgJsonPath.replace('package.json', '');
|
626
|
+
const pkgURL = pathToFileURL(pkgDr);
|
627
|
+
|
628
|
+
const context = {
|
442
629
|
importer,
|
443
|
-
|
630
|
+
importSpecifier,
|
631
|
+
moduleDirs: moduleDirectories,
|
632
|
+
pkgURL,
|
444
633
|
pkgJsonPath,
|
445
|
-
subPath: packageSubPath,
|
446
|
-
exportMap: pkgJson.exports,
|
447
634
|
conditions: exportConditions
|
448
|
-
}
|
449
|
-
const
|
450
|
-
|
635
|
+
};
|
636
|
+
const resolvedPackageExport = await resolvePackageExports(
|
637
|
+
context,
|
638
|
+
subpath,
|
639
|
+
pkgJson.exports
|
640
|
+
);
|
641
|
+
location = fileURLToPath(resolvedPackageExport);
|
451
642
|
} catch (error) {
|
643
|
+
if (!(error instanceof ResolveError)) {
|
644
|
+
throw error;
|
645
|
+
}
|
452
646
|
warn(error);
|
453
647
|
return null;
|
454
648
|
}
|
@@ -456,8 +650,9 @@ async function resolveId({
|
|
456
650
|
}
|
457
651
|
|
458
652
|
if (!location) {
|
653
|
+
// package has no imports or exports, use classic node resolve
|
459
654
|
try {
|
460
|
-
location = await resolveImportPath(
|
655
|
+
location = await resolveImportPath(importSpecifier, resolveOptions);
|
461
656
|
} catch (error) {
|
462
657
|
if (error.code !== 'MODULE_NOT_FOUND') {
|
463
658
|
throw error;
|
@@ -500,7 +695,7 @@ async function resolveImportSpecifiers({
|
|
500
695
|
// eslint-disable-next-line no-await-in-loop
|
501
696
|
const resolved = await resolveId({
|
502
697
|
importer,
|
503
|
-
|
698
|
+
importSpecifier: importSpecifierList[i],
|
504
699
|
exportConditions,
|
505
700
|
warn,
|
506
701
|
packageInfoCache,
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
File without changes
|