UNPKG

3.25 kBJavaScriptView Raw
1// @flow
2
3import type {ConfigRequestDesc, ParcelOptions} from './types';
4import type ParcelConfig from './ParcelConfig';
5
6import invariant from 'assert';
7import nullthrows from 'nullthrows';
8import {md5FromString, PromiseQueue} from '@parcel/utils';
9import {PluginLogger} from '@parcel/logger';
10import path from 'path';
11
12import {createConfig} from './InternalConfig';
13import Config from './public/Config';
14import loadParcelConfig from './loadParcelConfig';
15import loadPlugin from './loadParcelPlugin';
16
17export default class ConfigLoader {
18 options: ParcelOptions;
19 parcelConfig: ParcelConfig;
20 queue: PromiseQueue<any>;
21
22 constructor(options: ParcelOptions) {
23 this.options = options;
24 this.queue = new PromiseQueue({maxConcurrent: 32});
25 }
26
27 load(configRequest: ConfigRequestDesc) {
28 let promise = this.queue.add(() => this._load(configRequest));
29 this.queue.run();
30 return promise;
31 }
32
33 _load(configRequest: ConfigRequestDesc) {
34 if (!configRequest.plugin) {
35 return this.loadParcelConfig(configRequest);
36 }
37
38 return this.loadPluginConfig(configRequest);
39 }
40
41 async loadParcelConfig(configRequest: ConfigRequestDesc) {
42 let {filePath, isSource, env, pipeline} = configRequest;
43 let dir = isSource ? path.dirname(filePath) : this.options.projectRoot;
44 let searchPath = path.join(dir, 'index');
45 let config = createConfig({
46 isSource,
47 searchPath,
48 env,
49 });
50 let publicConfig = new Config(config, this.options);
51
52 let {config: parcelConfig, extendedFiles} = nullthrows(
53 await loadParcelConfig(searchPath, this.options),
54 );
55
56 publicConfig.setResolvedPath(parcelConfig.filePath);
57 publicConfig.setResult(parcelConfig.getConfig());
58 this.parcelConfig = parcelConfig;
59
60 let devDeps = [];
61 switch (configRequest.meta.actionType) {
62 case 'transformation':
63 devDeps = parcelConfig.getTransformerNames(filePath, pipeline);
64 break;
65 case 'validation':
66 devDeps = parcelConfig.getValidatorNames(filePath);
67 break;
68 case 'dependency':
69 devDeps = parcelConfig.getResolverNames();
70 break;
71 }
72 devDeps.forEach(devDep => publicConfig.addDevDependency(devDep));
73
74 publicConfig.setResultHash(md5FromString(JSON.stringify(devDeps)));
75
76 publicConfig.setWatchGlob('**/.parcelrc');
77
78 // TODO: if extended config comes from a package, yarn.lock change should invalidate config request
79 for (let extendedFile of extendedFiles) {
80 publicConfig.addIncludedFile(extendedFile);
81 }
82
83 return config;
84 }
85
86 async loadPluginConfig({
87 plugin,
88 env,
89 isSource,
90 filePath,
91 meta: {parcelConfigPath},
92 }: ConfigRequestDesc) {
93 let config = createConfig({
94 isSource,
95 searchPath: filePath,
96 env,
97 });
98 invariant(typeof parcelConfigPath === 'string');
99 let pluginInstance = await loadPlugin(
100 this.options.packageManager,
101 nullthrows(plugin),
102 parcelConfigPath,
103 );
104 if (pluginInstance.loadConfig != null) {
105 await pluginInstance.loadConfig({
106 config: new Config(config, this.options),
107 options: this.options,
108 logger: new PluginLogger({origin: nullthrows(plugin)}),
109 });
110 }
111
112 return config;
113 }
114}