1 |
|
2 |
|
3 | import type {ConfigRequestDesc, ParcelOptions} from './types';
|
4 | import type ParcelConfig from './ParcelConfig';
|
5 |
|
6 | import invariant from 'assert';
|
7 | import nullthrows from 'nullthrows';
|
8 | import {md5FromString, PromiseQueue} from '@parcel/utils';
|
9 | import {PluginLogger} from '@parcel/logger';
|
10 | import path from 'path';
|
11 |
|
12 | import {createConfig} from './InternalConfig';
|
13 | import Config from './public/Config';
|
14 | import loadParcelConfig from './loadParcelConfig';
|
15 | import loadPlugin from './loadParcelPlugin';
|
16 |
|
17 | export 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 |
|
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 | }
|