/
resolveId.ts
74 lines (68 loc) · 2.46 KB
/
resolveId.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
import type { CustomPluginOptions, Plugin, ResolvedId, ResolveIdResult } from '../rollup/types';
import type { PluginDriver } from './PluginDriver';
import { promises as fs } from './fs';
import { basename, dirname, isAbsolute, resolve } from './path';
import { resolveIdViaPlugins } from './resolveIdViaPlugins';
export async function resolveId(
source: string,
importer: string | undefined,
preserveSymlinks: boolean,
pluginDriver: PluginDriver,
moduleLoaderResolveId: (
source: string,
importer: string | undefined,
customOptions: CustomPluginOptions | undefined,
isEntry: boolean | undefined,
skip: readonly { importer: string | undefined; plugin: Plugin; source: string }[] | null
) => Promise<ResolvedId | null>,
skip: readonly { importer: string | undefined; plugin: Plugin; source: string }[] | null,
customOptions: CustomPluginOptions | undefined,
isEntry: boolean
): Promise<ResolveIdResult> {
const pluginResult = await resolveIdViaPlugins(
source,
importer,
pluginDriver,
moduleLoaderResolveId,
skip,
customOptions,
isEntry
);
if (pluginResult != null) return pluginResult;
// external modules (non-entry modules that start with neither '.' or '/')
// are skipped at this stage.
if (importer !== undefined && !isAbsolute(source) && source[0] !== '.') return null;
// `resolve` processes paths from right to left, prepending them until an
// absolute path is created. Absolute importees therefore shortcircuit the
// resolve call and require no special handing on our part.
// See https://nodejs.org/api/path.html#path_path_resolve_paths
return addJsExtensionIfNecessary(
importer ? resolve(dirname(importer), source) : resolve(source),
preserveSymlinks
);
}
async function addJsExtensionIfNecessary(
file: string,
preserveSymlinks: boolean
): Promise<string | undefined> {
return (
(await findFile(file, preserveSymlinks)) ??
(await findFile(file + '.mjs', preserveSymlinks)) ??
(await findFile(file + '.js', preserveSymlinks))
);
}
async function findFile(file: string, preserveSymlinks: boolean): Promise<string | undefined> {
try {
const stats = await fs.lstat(file);
if (!preserveSymlinks && stats.isSymbolicLink())
return await findFile(await fs.realpath(file), preserveSymlinks);
if ((preserveSymlinks && stats.isSymbolicLink()) || stats.isFile()) {
// check case
const name = basename(file);
const files = await fs.readdir(dirname(file));
if (files.includes(name)) return file;
}
} catch {
// suppress
}
}