UNPKG

11.4 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.computeDefaultAppDirectory = exports.validateConfiguration = exports.doMergeConfigs = exports.getConfig = void 0;
4const builder_util_1 = require("builder-util");
5const fs_1 = require("builder-util/out/fs");
6const fs_extra_1 = require("fs-extra");
7const lazy_val_1 = require("lazy-val");
8const path = require("path");
9const read_config_file_1 = require("read-config-file");
10const rectCra_1 = require("../presets/rectCra");
11const version_1 = require("../version");
12// eslint-disable-next-line @typescript-eslint/no-var-requires
13const validateSchema = require("@develar/schema-utils");
14// https://github.com/electron-userland/electron-builder/issues/1847
15function mergePublish(config, configFromOptions) {
16 // if config from disk doesn't have publish (or object), no need to handle, it will be simply merged by deepAssign
17 const publish = Array.isArray(config.publish) ? configFromOptions.publish : null;
18 if (publish != null) {
19 delete configFromOptions.publish;
20 }
21 (0, builder_util_1.deepAssign)(config, configFromOptions);
22 if (publish == null) {
23 return;
24 }
25 const listOnDisk = config.publish;
26 if (listOnDisk.length === 0) {
27 config.publish = publish;
28 }
29 else {
30 // apply to first
31 Object.assign(listOnDisk[0], publish);
32 }
33}
34async function getConfig(projectDir, configPath, configFromOptions, packageMetadata = new lazy_val_1.Lazy(() => (0, read_config_file_1.orNullIfFileNotExist)((0, fs_extra_1.readJson)(path.join(projectDir, "package.json"))))) {
35 const configRequest = { packageKey: "build", configFilename: "electron-builder", projectDir, packageMetadata };
36 const configAndEffectiveFile = await (0, read_config_file_1.getConfig)(configRequest, configPath);
37 const config = configAndEffectiveFile == null ? {} : configAndEffectiveFile.result;
38 if (configFromOptions != null) {
39 mergePublish(config, configFromOptions);
40 }
41 if (configAndEffectiveFile != null) {
42 builder_util_1.log.info({ file: configAndEffectiveFile.configFile == null ? 'package.json ("build" field)' : configAndEffectiveFile.configFile }, "loaded configuration");
43 }
44 if (config.extends == null && config.extends !== null) {
45 const metadata = (await packageMetadata.value) || {};
46 const devDependencies = metadata.devDependencies;
47 const dependencies = metadata.dependencies;
48 if ((dependencies != null && "react-scripts" in dependencies) || (devDependencies != null && "react-scripts" in devDependencies)) {
49 config.extends = "react-cra";
50 }
51 else if (devDependencies != null && "electron-webpack" in devDependencies) {
52 let file = "electron-webpack/out/electron-builder.js";
53 try {
54 file = require.resolve(file);
55 }
56 catch (ignore) {
57 file = require.resolve("electron-webpack/electron-builder.yml");
58 }
59 config.extends = `file:${file}`;
60 }
61 }
62 const parentConfigs = await loadParentConfigsRecursively(config.extends, async (configExtend) => {
63 if (configExtend === "react-cra") {
64 const result = await (0, rectCra_1.reactCra)(projectDir);
65 builder_util_1.log.info({ preset: configExtend }, "loaded parent configuration");
66 return result;
67 }
68 else {
69 const { configFile, result } = await (0, read_config_file_1.loadParentConfig)(configRequest, configExtend);
70 builder_util_1.log.info({ file: configFile }, "loaded parent configuration");
71 return result;
72 }
73 });
74 return doMergeConfigs([...parentConfigs, config]);
75}
76exports.getConfig = getConfig;
77function asArray(value) {
78 return Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
79}
80async function loadParentConfigsRecursively(configExtends, loader) {
81 const configs = [];
82 for (const configExtend of asArray(configExtends)) {
83 const result = await loader(configExtend);
84 const parentConfigs = await loadParentConfigsRecursively(result.extends, loader);
85 configs.push(...parentConfigs, result);
86 }
87 return configs;
88}
89// normalize for easy merge
90function normalizeFiles(configuration, name) {
91 let value = configuration[name];
92 if (value == null) {
93 return;
94 }
95 if (!Array.isArray(value)) {
96 value = [value];
97 }
98 itemLoop: for (let i = 0; i < value.length; i++) {
99 let item = value[i];
100 if (typeof item === "string") {
101 // merge with previous if possible
102 if (i !== 0) {
103 let prevItemIndex = i - 1;
104 let prevItem;
105 do {
106 prevItem = value[prevItemIndex--];
107 } while (prevItem == null);
108 if (prevItem.from == null && prevItem.to == null) {
109 if (prevItem.filter == null) {
110 prevItem.filter = [item];
111 }
112 else {
113 ;
114 prevItem.filter.push(item);
115 }
116 value[i] = null;
117 continue itemLoop;
118 }
119 }
120 item = {
121 filter: [item],
122 };
123 value[i] = item;
124 }
125 else if (Array.isArray(item)) {
126 throw new Error(`${name} configuration is invalid, nested array not expected for index ${i}: ${item}`);
127 }
128 // make sure that merge logic is not complex - unify different presentations
129 if (item.from === ".") {
130 item.from = undefined;
131 }
132 if (item.to === ".") {
133 item.to = undefined;
134 }
135 if (item.filter != null && typeof item.filter === "string") {
136 item.filter = [item.filter];
137 }
138 }
139 configuration[name] = value.filter(it => it != null);
140}
141function isSimilarFileSet(value, other) {
142 return value.from === other.from && value.to === other.to;
143}
144function mergeFilters(value, other) {
145 return asArray(value).concat(asArray(other));
146}
147function mergeFileSets(lists) {
148 const result = [];
149 for (const list of lists) {
150 for (const item of list) {
151 const existingItem = result.find(i => isSimilarFileSet(i, item));
152 if (existingItem) {
153 existingItem.filter = mergeFilters(item.filter, existingItem.filter);
154 }
155 else {
156 result.push(item);
157 }
158 }
159 }
160 return result;
161}
162/**
163 * `doMergeConfigs` takes configs in the order you would pass them to
164 * Object.assign as sources.
165 */
166function doMergeConfigs(configs) {
167 for (const config of configs) {
168 normalizeFiles(config, "files");
169 normalizeFiles(config, "extraFiles");
170 normalizeFiles(config, "extraResources");
171 }
172 const result = (0, builder_util_1.deepAssign)(getDefaultConfig(), ...configs);
173 // `deepAssign` prioritises latter configs, while `mergeFilesSets` prioritises
174 // former configs, so we have to reverse the order, because latter configs
175 // must have higher priority.
176 configs = configs.slice().reverse();
177 result.files = mergeFileSets(configs.map(config => { var _a; return ((_a = config.files) !== null && _a !== void 0 ? _a : []); }));
178 return result;
179}
180exports.doMergeConfigs = doMergeConfigs;
181function getDefaultConfig() {
182 return {
183 directories: {
184 output: "dist",
185 buildResources: "build",
186 },
187 };
188}
189const schemeDataPromise = new lazy_val_1.Lazy(() => (0, fs_extra_1.readJson)(path.join(__dirname, "..", "..", "scheme.json")));
190async function validateConfiguration(config, debugLogger) {
191 const extraMetadata = config.extraMetadata;
192 if (extraMetadata != null) {
193 if (extraMetadata.build != null) {
194 throw new builder_util_1.InvalidConfigurationError(`--em.build is deprecated, please specify as -c"`);
195 }
196 if (extraMetadata.directories != null) {
197 throw new builder_util_1.InvalidConfigurationError(`--em.directories is deprecated, please specify as -c.directories"`);
198 }
199 }
200 const oldConfig = config;
201 if (oldConfig.npmSkipBuildFromSource === false) {
202 throw new builder_util_1.InvalidConfigurationError(`npmSkipBuildFromSource is deprecated, please use buildDependenciesFromSource"`);
203 }
204 if (oldConfig.appImage != null && oldConfig.appImage.systemIntegration != null) {
205 throw new builder_util_1.InvalidConfigurationError(`appImage.systemIntegration is deprecated, https://github.com/TheAssassin/AppImageLauncher is used for desktop integration"`);
206 }
207 // noinspection JSUnusedGlobalSymbols
208 validateSchema(await schemeDataPromise.value, config, {
209 name: `electron-builder ${version_1.PACKAGE_VERSION}`,
210 postFormatter: (formattedError, error) => {
211 if (debugLogger.isEnabled) {
212 debugLogger.add("invalidConfig", (0, builder_util_1.safeStringifyJson)(error));
213 }
214 const site = "https://www.electron.build";
215 let url = `${site}/configuration/configuration`;
216 const targets = new Set(["mac", "dmg", "pkg", "mas", "win", "nsis", "appx", "linux", "appimage", "snap"]);
217 const dataPath = error.dataPath == null ? null : error.dataPath;
218 const targetPath = dataPath.startsWith(".") ? dataPath.substr(1).toLowerCase() : null;
219 if (targetPath != null && targets.has(targetPath)) {
220 url = `${site}/configuration/${targetPath}`;
221 }
222 return `${formattedError}\n How to fix:
223 1. Open ${url}
224 2. Search the option name on the page (or type in into Search to find across the docs).
225 * Not found? The option was deprecated or not exists (check spelling).
226 * Found? Check that the option in the appropriate place. e.g. "title" only in the "dmg", not in the root.
227`;
228 },
229 });
230}
231exports.validateConfiguration = validateConfiguration;
232const DEFAULT_APP_DIR_NAMES = ["app", "www"];
233async function computeDefaultAppDirectory(projectDir, userAppDir) {
234 if (userAppDir != null) {
235 const absolutePath = path.resolve(projectDir, userAppDir);
236 const stat = await (0, fs_1.statOrNull)(absolutePath);
237 if (stat == null) {
238 throw new builder_util_1.InvalidConfigurationError(`Application directory ${userAppDir} doesn't exist`);
239 }
240 else if (!stat.isDirectory()) {
241 throw new builder_util_1.InvalidConfigurationError(`Application directory ${userAppDir} is not a directory`);
242 }
243 else if (projectDir === absolutePath) {
244 builder_util_1.log.warn({ appDirectory: userAppDir }, `Specified application directory equals to project dir — superfluous or wrong configuration`);
245 }
246 return absolutePath;
247 }
248 for (const dir of DEFAULT_APP_DIR_NAMES) {
249 const absolutePath = path.join(projectDir, dir);
250 const packageJson = path.join(absolutePath, "package.json");
251 const stat = await (0, fs_1.statOrNull)(packageJson);
252 if (stat != null && stat.isFile()) {
253 return absolutePath;
254 }
255 }
256 return projectDir;
257}
258exports.computeDefaultAppDirectory = computeDefaultAppDirectory;
259//# sourceMappingURL=config.js.map
\No newline at end of file