1 | import importedPath from 'path'
|
2 | import { ResolverIO } from './types'
|
3 |
|
4 |
|
5 | const uniq = arr => arr.filter((elem, pos, a) => a.indexOf(elem) === pos)
|
6 | const reversePathsToWalk = ({ folder, path }) => {
|
7 | const resolved = path.resolve(folder)
|
8 | const parts = resolved.split(path.sep)
|
9 | const results = parts.map((_, idx, arr) =>
|
10 | arr.slice(0, idx + 1).join(path.sep),
|
11 | )
|
12 | results[0] = results[0] || '/'
|
13 | return results.reverse()
|
14 | }
|
15 |
|
16 | const configLookup = (file: string, folder: string, path: any = importedPath) =>
|
17 | uniq(reversePathsToWalk({ folder, path }).map(p => path.join(p, file)))
|
18 |
|
19 | class ConfigResolver {
|
20 | configFile: string
|
21 |
|
22 | io: ResolverIO
|
23 |
|
24 | constructor(configFile: string, io: ResolverIO) {
|
25 | this.configFile = configFile
|
26 | this.io = io
|
27 | }
|
28 |
|
29 | async resolve(from: string) {
|
30 | const configCandidates = configLookup(this.configFile, from)
|
31 | const { exists, load, none } = this.io
|
32 | for (const candidate of configCandidates) {
|
33 | if (await exists(candidate)) {
|
34 | return load(candidate)
|
35 | }
|
36 | }
|
37 | return none(from)
|
38 | }
|
39 | }
|
40 |
|
41 | export { configLookup, ConfigResolver, reversePathsToWalk }
|