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