1 | 'use strict'
|
2 | exports.__esModule = true
|
3 |
|
4 | const pkgDir = require('pkg-dir')
|
5 |
|
6 | const fs = require('fs')
|
7 | const path = require('path')
|
8 |
|
9 | const hashObject = require('./hash').hashObject
|
10 | , ModuleCache = require('./ModuleCache').default
|
11 |
|
12 | const CASE_SENSITIVE_FS = !fs.existsSync(path.join(__dirname, 'reSOLVE.js'))
|
13 | exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS
|
14 |
|
15 | const fileExistsCache = new ModuleCache()
|
16 |
|
17 | function tryRequire(target) {
|
18 | let resolved
|
19 | try {
|
20 |
|
21 | resolved = require.resolve(target)
|
22 | } catch(e) {
|
23 |
|
24 | return undefined
|
25 | }
|
26 |
|
27 |
|
28 | return require(resolved)
|
29 | }
|
30 |
|
31 |
|
32 | exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings) {
|
33 |
|
34 | if (CASE_SENSITIVE_FS) return true
|
35 |
|
36 |
|
37 | if (filepath === null) return true
|
38 | if (filepath.toLowerCase() === process.cwd().toLowerCase()) return true
|
39 | const parsedPath = path.parse(filepath)
|
40 | , dir = parsedPath.dir
|
41 |
|
42 | let result = fileExistsCache.get(filepath, cacheSettings)
|
43 | if (result != null) return result
|
44 |
|
45 |
|
46 | if (dir === '' || parsedPath.root === filepath) {
|
47 | result = true
|
48 | } else {
|
49 | const filenames = fs.readdirSync(dir)
|
50 | if (filenames.indexOf(parsedPath.base) === -1) {
|
51 | result = false
|
52 | } else {
|
53 | result = fileExistsWithCaseSync(dir, cacheSettings)
|
54 | }
|
55 | }
|
56 | fileExistsCache.set(filepath, result)
|
57 | return result
|
58 | }
|
59 |
|
60 | function relative(modulePath, sourceFile, settings) {
|
61 | return fullResolve(modulePath, sourceFile, settings).path
|
62 | }
|
63 |
|
64 | function fullResolve(modulePath, sourceFile, settings) {
|
65 |
|
66 | const coreSet = new Set(settings['import/core-modules'])
|
67 | if (coreSet.has(modulePath)) return { found: true, path: null }
|
68 |
|
69 | const sourceDir = path.dirname(sourceFile)
|
70 | , cacheKey = sourceDir + hashObject(settings).digest('hex') + modulePath
|
71 |
|
72 | const cacheSettings = ModuleCache.getSettings(settings)
|
73 |
|
74 | const cachedPath = fileExistsCache.get(cacheKey, cacheSettings)
|
75 | if (cachedPath !== undefined) return { found: true, path: cachedPath }
|
76 |
|
77 | function cache(resolvedPath) {
|
78 | fileExistsCache.set(cacheKey, resolvedPath)
|
79 | }
|
80 |
|
81 | function withResolver(resolver, config) {
|
82 |
|
83 | function v1() {
|
84 | try {
|
85 | const resolved = resolver.resolveImport(modulePath, sourceFile, config)
|
86 | if (resolved === undefined) return { found: false }
|
87 | return { found: true, path: resolved }
|
88 | } catch (err) {
|
89 | return { found: false }
|
90 | }
|
91 | }
|
92 |
|
93 | function v2() {
|
94 | return resolver.resolve(modulePath, sourceFile, config)
|
95 | }
|
96 |
|
97 | switch (resolver.interfaceVersion) {
|
98 | case 2:
|
99 | return v2()
|
100 |
|
101 | default:
|
102 | case 1:
|
103 | return v1()
|
104 | }
|
105 | }
|
106 |
|
107 | const configResolvers = (settings['import/resolver']
|
108 | || { 'node': settings['import/resolve'] })
|
109 |
|
110 | const resolvers = resolverReducer(configResolvers, new Map())
|
111 |
|
112 | for (let pair of resolvers) {
|
113 | let name = pair[0]
|
114 | , config = pair[1]
|
115 | const resolver = requireResolver(name, sourceFile)
|
116 | , resolved = withResolver(resolver, config)
|
117 |
|
118 | if (!resolved.found) continue
|
119 |
|
120 |
|
121 | cache(resolved.path)
|
122 | return resolved
|
123 | }
|
124 |
|
125 |
|
126 |
|
127 | return { found: false }
|
128 | }
|
129 | exports.relative = relative
|
130 |
|
131 | function resolverReducer(resolvers, map) {
|
132 | if (resolvers instanceof Array) {
|
133 | resolvers.forEach(r => resolverReducer(r, map))
|
134 | return map
|
135 | }
|
136 |
|
137 | if (typeof resolvers === 'string') {
|
138 | map.set(resolvers, null)
|
139 | return map
|
140 | }
|
141 |
|
142 | if (typeof resolvers === 'object') {
|
143 | for (let key in resolvers) {
|
144 | map.set(key, resolvers[key])
|
145 | }
|
146 | return map
|
147 | }
|
148 |
|
149 | throw new Error('invalid resolver config')
|
150 | }
|
151 |
|
152 | function getBaseDir(sourceFile) {
|
153 | return pkgDir.sync(sourceFile) || process.cwd()
|
154 | }
|
155 | function requireResolver(name, sourceFile) {
|
156 |
|
157 | let resolver = tryRequire(`eslint-import-resolver-${name}`) ||
|
158 | tryRequire(name) ||
|
159 | tryRequire(path.resolve(getBaseDir(sourceFile), name))
|
160 |
|
161 | if (!resolver) {
|
162 | throw new Error(`unable to load resolver "${name}".`)
|
163 | }
|
164 | if (!isResolverValid(resolver)) {
|
165 | throw new Error(`${name} with invalid interface loaded as resolver`)
|
166 | }
|
167 |
|
168 | return resolver
|
169 | }
|
170 |
|
171 | function isResolverValid(resolver) {
|
172 | if (resolver.interfaceVersion === 2) {
|
173 | return resolver.resolve && typeof resolver.resolve === 'function'
|
174 | } else {
|
175 | return resolver.resolveImport && typeof resolver.resolveImport === 'function'
|
176 | }
|
177 | }
|
178 |
|
179 | const erroredContexts = new Set()
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 | function resolve(p, context) {
|
190 | try {
|
191 | return relative( p
|
192 | , context.getFilename()
|
193 | , context.settings
|
194 | )
|
195 | } catch (err) {
|
196 | if (!erroredContexts.has(context)) {
|
197 | context.report({
|
198 | message: `Resolve error: ${err.message}`,
|
199 | loc: { line: 1, column: 0 },
|
200 | })
|
201 | erroredContexts.add(context)
|
202 | }
|
203 | }
|
204 | }
|
205 | resolve.relative = relative
|
206 | exports.default = resolve
|