-
Notifications
You must be signed in to change notification settings - Fork 0
/
pnp-resolution.ts
97 lines (82 loc) · 3.17 KB
/
pnp-resolution.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/** Fork and reimplementation of pnp's resolution to support browser and exports fields. */
import * as fs from 'fs';
import { join, normalize, sep } from 'path';
import type PnpApiNamespace from 'pnpapi';
import { resolve, legacy } from 'resolve.exports';
type PnpApi = typeof PnpApiNamespace;
const extensions = ['.tsx', '.ts', '.jsx', '.mjs', '.cjs', '.js', '.json'];
const isStrictRegExp = /^(\/|\.{1,2}(\/|$))/;
const isRelativeRegexp = /^\.{0,2}\//;
export const resolvePackageEntry = (
packageJsonContent: unknown,
entry: string,
browser: boolean
): string | null => {
const exportedPath = resolve(packageJsonContent, entry, { browser, require: !browser });
if (exportedPath != null) return exportedPath;
if (entry !== '.') return null;
const legacyPath = legacy(
packageJsonContent,
browser ? { browser } : { browser: false, fields: ['main', 'module'] }
);
return typeof legacyPath === 'string' ? legacyPath : null;
};
const pathContains = (pathFrom: string, pathTo: string): string | null => {
let from = normalize(pathFrom);
const to = normalize(pathTo);
if (from === to) return '.';
if (!from.endsWith(sep)) from = from + sep;
return to.startsWith(from) ? to.slice(from.length) : null;
};
/**
* Forked from Yarn:
* https://github.com/yarnpkg/berry/blob/30e1d3c52f895721aefd55dea8f21b75bdf3d4ff/packages/yarnpkg-pnp/sources/loader/makeApi.ts#L202-L245
*/
const applyNodeExportsResolution = (unqualifiedPath: string, pnpApi: PnpApi, browser: boolean) => {
const locator = pnpApi.findPackageLocator(join(unqualifiedPath, 'internal.js'));
if (locator == null) throw new Error();
const { packageLocation } = pnpApi.getPackageInformation(locator);
const manifestPath = join(packageLocation, 'package.json');
if (!fs.existsSync(manifestPath)) return null;
const pkgJson = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
let subpath = pathContains(packageLocation, unqualifiedPath);
if (subpath == null) throw new Error();
if (!isRelativeRegexp.test(subpath)) subpath = `./${subpath}`;
subpath = normalize(subpath);
const remappedSubpath = resolvePackageEntry(pkgJson, subpath, browser);
return remappedSubpath != null ? join(packageLocation, remappedSubpath) : null;
};
/**
* Copied from Yarn:
* https://github.com/yarnpkg/berry/blob/30e1d3c52f895721aefd55dea8f21b75bdf3d4ff/packages/yarnpkg-pnp/sources/loader/makeApi.ts#L781-L791
*/
const resolveUnqualifiedExport = (
request: string,
unqualifiedPath: string,
pnpApi: PnpApi,
browser: boolean
): string => {
if (isStrictRegExp.test(request)) {
return unqualifiedPath;
}
const unqualifiedExportPath = applyNodeExportsResolution(unqualifiedPath, pnpApi, browser);
if (unqualifiedExportPath) {
return normalize(unqualifiedExportPath);
} else {
return unqualifiedPath;
}
};
const resolveRequest = (
request: string,
issuer: string,
pnpApi: PnpApi,
browser: boolean
): string | null => {
const unqualifiedPath = pnpApi.resolveToUnqualified(request, issuer);
if (unqualifiedPath == null) return null;
return pnpApi.resolveUnqualified(
resolveUnqualifiedExport(request, unqualifiedPath, pnpApi, browser),
{ extensions }
);
};
export default resolveRequest;