UNPKG

6.8 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = loadParcelConfig;
7exports.resolveParcelConfig = resolveParcelConfig;
8exports.create = create;
9exports.readAndProcess = readAndProcess;
10exports.processConfig = processConfig;
11exports.resolveExtends = resolveExtends;
12exports.validateConfigFile = validateConfigFile;
13exports.validateNotEmpty = validateNotEmpty;
14exports.mergeConfigs = mergeConfigs;
15exports.mergePipelines = mergePipelines;
16exports.mergeMaps = mergeMaps;
17
18var _utils = require("@parcel/utils");
19
20var _json = require("json5");
21
22var _path = _interopRequireDefault(require("path"));
23
24var _assert = _interopRequireDefault(require("assert"));
25
26var _ParcelConfig = _interopRequireDefault(require("./ParcelConfig"));
27
28var _ParcelConfig2 = _interopRequireDefault(require("./ParcelConfig.schema"));
29
30function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
32function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
33
34function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
35
36function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
37
38async function loadParcelConfig(filePath, options) {
39 // Resolve plugins from cwd when a config is passed programmatically
40 let parcelConfig = options.config ? await create(_objectSpread({}, options.config, {
41 resolveFrom: options.inputFS.cwd()
42 }), options) : await resolveParcelConfig(filePath, options);
43
44 if (!parcelConfig && options.defaultConfig) {
45 parcelConfig = await create(_objectSpread({}, options.defaultConfig, {
46 resolveFrom: options.inputFS.cwd()
47 }), options);
48 }
49
50 if (!parcelConfig) {
51 throw new Error('Could not find a .parcelrc');
52 }
53
54 return parcelConfig;
55}
56
57async function resolveParcelConfig(filePath, options) {
58 let configPath = await (0, _utils.resolveConfig)(options.inputFS, filePath, ['.parcelrc']);
59
60 if (!configPath) {
61 return null;
62 }
63
64 return readAndProcess(configPath, options);
65}
66
67function create(config, options) {
68 return processConfig(config, config.filePath, options);
69}
70
71async function readAndProcess(configPath, options) {
72 let config = (0, _json.parse)((await options.inputFS.readFile(configPath)));
73 return processConfig(config, configPath, options);
74}
75
76async function processConfig(configFile, filePath, options) {
77 let resolvedFile = _objectSpread({
78 filePath
79 }, configFile);
80
81 let config = new _ParcelConfig.default(resolvedFile, options.packageManager);
82
83 let relativePath = _path.default.relative(options.inputFS.cwd(), filePath);
84
85 validateConfigFile(configFile, relativePath);
86 let extendedFiles = [];
87
88 if (configFile.extends) {
89 let exts = Array.isArray(configFile.extends) ? configFile.extends : [configFile.extends];
90
91 for (let ext of exts) {
92 let resolved = await resolveExtends(ext, filePath, options);
93 extendedFiles.push(resolved);
94 let {
95 extendedFiles: moreExtendedFiles,
96 config: baseConfig
97 } = await readAndProcess(resolved, options);
98 extendedFiles = extendedFiles.concat(moreExtendedFiles);
99 config = mergeConfigs(baseConfig, resolvedFile);
100 }
101 }
102
103 return {
104 config,
105 extendedFiles
106 };
107}
108
109async function resolveExtends(ext, configPath, options) {
110 if (ext.startsWith('.')) {
111 return _path.default.resolve(_path.default.dirname(configPath), ext);
112 } else {
113 let {
114 resolved
115 } = await (0, _utils.resolve)(options.inputFS, ext, {
116 basedir: _path.default.dirname(configPath),
117 extensions: ['.json']
118 });
119 return options.inputFS.realpath(resolved);
120 }
121}
122
123function validateConfigFile(config, relativePath) {
124 validateNotEmpty(config, relativePath);
125
126 _utils.validateSchema.diagnostic(_ParcelConfig2.default, config, relativePath, JSON.stringify(config, null, '\t'), '@parcel/core', '', 'Invalid Parcel Config');
127}
128
129function validateNotEmpty(config, relativePath) {
130 _assert.default.notDeepStrictEqual(config, {}, `${relativePath} can't be empty`);
131}
132
133function mergeConfigs(base, ext) {
134 return new _ParcelConfig.default({
135 filePath: ext.filePath,
136 // TODO: revisit this - it should resolve plugins based on the actual config they are defined in
137 resolvers: mergePipelines(base.resolvers, ext.resolvers),
138 transforms: mergeMaps(base.transforms, ext.transforms, mergePipelines),
139 validators: mergeMaps(base.validators, ext.validators, mergePipelines),
140 bundler: ext.bundler || base.bundler,
141 namers: mergePipelines(base.namers, ext.namers),
142 runtimes: mergeMaps(base.runtimes, ext.runtimes),
143 packagers: mergeMaps(base.packagers, ext.packagers),
144 optimizers: mergeMaps(base.optimizers, ext.optimizers, mergePipelines),
145 reporters: mergePipelines(base.reporters, ext.reporters)
146 }, base.packageManager);
147}
148
149function mergePipelines(base, ext) {
150 if (!ext) {
151 return base || [];
152 }
153
154 if (base) {
155 // Merge the base pipeline if a rest element is defined
156 let spreadIndex = ext.indexOf('...');
157
158 if (spreadIndex >= 0) {
159 if (ext.filter(v => v === '...').length > 1) {
160 throw new Error('Only one spread element can be included in a config pipeline');
161 }
162
163 ext = [...ext.slice(0, spreadIndex), ...(base || []), ...ext.slice(spreadIndex + 1)];
164 }
165 }
166
167 return ext;
168}
169
170function mergeMaps(base, ext, merger) {
171 if (!ext) {
172 return base || {};
173 }
174
175 if (!base) {
176 return ext;
177 } // Add the extension options first so they have higher precedence in the output glob map
178
179
180 let res = {};
181
182 for (let k in ext) {
183 // Flow doesn't correctly infer the type. See https://github.com/facebook/flow/issues/1736.
184 let key = k;
185 res[key] = merger && base[key] ? merger(base[key], ext[key]) : ext[key];
186 } // Add base options that aren't defined in the extension
187
188
189 for (let k in base) {
190 let key = k;
191
192 if (!res[key]) {
193 res[key] = base[key];
194 }
195 }
196
197 return res;
198}
\No newline at end of file