UNPKG

2.78 kBJavaScriptView Raw
1// @flow
2
3import type {ConfigResult, File, FilePath} from '@parcel/types';
4import type {FileSystem} from '@parcel/fs';
5import path from 'path';
6import clone from 'clone';
7
8export type ConfigOutput = {|
9 config: ConfigResult,
10 files: Array<File>,
11|};
12
13export type ConfigOptions = {|
14 parse?: boolean,
15|};
16
17const PARSERS = {
18 json: require('json5').parse,
19 toml: require('@iarna/toml').parse,
20};
21
22export async function resolveConfig(
23 fs: FileSystem,
24 filepath: FilePath,
25 filenames: Array<FilePath>,
26 opts: ?ConfigOptions,
27 root: FilePath = path.parse(filepath).root,
28): Promise<FilePath | null> {
29 filepath = await fs.realpath(path.dirname(filepath));
30
31 // Don't traverse above the module root
32 if (path.basename(filepath) === 'node_modules') {
33 return null;
34 }
35
36 for (const filename of filenames) {
37 let file = path.join(filepath, filename);
38 if ((await fs.exists(file)) && (await fs.stat(file)).isFile()) {
39 return file;
40 }
41 }
42
43 if (filepath === root) {
44 return null;
45 }
46
47 return resolveConfig(fs, filepath, filenames, opts);
48}
49
50export function resolveConfigSync(
51 fs: FileSystem,
52 filepath: FilePath,
53 filenames: Array<FilePath>,
54 opts: ?ConfigOptions,
55 root: FilePath = path.parse(filepath).root,
56): FilePath | null {
57 filepath = fs.realpathSync(path.dirname(filepath));
58
59 // Don't traverse above the module root
60 if (filepath === root || path.basename(filepath) === 'node_modules') {
61 return null;
62 }
63
64 for (const filename of filenames) {
65 let file = path.join(filepath, filename);
66 if (fs.existsSync(file) && fs.statSync(file).isFile()) {
67 return file;
68 }
69 }
70
71 return resolveConfigSync(fs, filepath, filenames, opts);
72}
73
74export async function loadConfig(
75 fs: FileSystem,
76 filepath: FilePath,
77 filenames: Array<FilePath>,
78 opts: ?ConfigOptions,
79): Promise<ConfigOutput | null> {
80 let configFile = await resolveConfig(fs, filepath, filenames, opts);
81 if (configFile) {
82 try {
83 let extname = path.extname(configFile).slice(1);
84 if (extname === 'js') {
85 return {
86 // $FlowFixMe
87 config: clone(require(configFile)),
88 files: [{filePath: configFile}],
89 };
90 }
91
92 let configContent = await fs.readFile(configFile, 'utf8');
93 if (!configContent) {
94 return null;
95 }
96
97 let config;
98 if (opts && opts.parse === false) {
99 config = configContent;
100 } else {
101 let parse = PARSERS[extname] || PARSERS.json;
102 config = parse(configContent);
103 }
104
105 return {
106 config: config,
107 files: [{filePath: configFile}],
108 };
109 } catch (err) {
110 if (err.code === 'MODULE_NOT_FOUND' || err.code === 'ENOENT') {
111 return null;
112 }
113
114 throw err;
115 }
116 }
117
118 return null;
119}