This commit is contained in:
2026-03-25 14:14:07 +01:00
parent d6b31e2ef7
commit a0073b4fb1
10368 changed files with 2214340 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
import { DebugLogger } from "builder-util";
import { Lazy } from "lazy-val";
import { Configuration } from "../../configuration";
export declare function getConfig(projectDir: string, configPath: string | null, configFromOptions: Configuration | null | undefined, packageMetadata?: Lazy<{
[key: string]: any;
} | null>): Promise<Configuration>;
/**
* `doMergeConfigs` takes configs in the order you would pass them to
* Object.assign as sources.
*/
export declare function doMergeConfigs(configs: Configuration[]): Configuration;
export declare function validateConfiguration(config: Configuration, debugLogger: DebugLogger): Promise<void>;
export declare function computeDefaultAppDirectory(projectDir: string, userAppDir: string | null | undefined): Promise<string>;

View File

@@ -0,0 +1,256 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getConfig = getConfig;
exports.doMergeConfigs = doMergeConfigs;
exports.validateConfiguration = validateConfiguration;
exports.computeDefaultAppDirectory = computeDefaultAppDirectory;
const builder_util_1 = require("builder-util");
const fs_extra_1 = require("fs-extra");
const lazy_val_1 = require("lazy-val");
const path = require("path");
const load_1 = require("./load");
const rectCra_1 = require("../../presets/rectCra");
const version_1 = require("../../version");
const validateSchema = require("@develar/schema-utils");
// https://github.com/electron-userland/electron-builder/issues/1847
function mergePublish(config, configFromOptions) {
// if config from disk doesn't have publish (or object), no need to handle, it will be simply merged by deepAssign
const publish = Array.isArray(config.publish) ? configFromOptions.publish : null;
if (publish != null) {
delete configFromOptions.publish;
}
(0, builder_util_1.deepAssign)(config, configFromOptions);
if (publish == null) {
return;
}
const listOnDisk = config.publish;
if (listOnDisk.length === 0) {
config.publish = publish;
}
else {
// apply to first
Object.assign(listOnDisk[0], publish);
}
}
async function getConfig(projectDir, configPath, configFromOptions, packageMetadata = new lazy_val_1.Lazy(() => (0, load_1.orNullIfFileNotExist)((0, fs_extra_1.readJson)(path.join(projectDir, "package.json"))))) {
const configRequest = { packageKey: "build", configFilename: "electron-builder", projectDir, packageMetadata };
const configAndEffectiveFile = await (0, load_1.getConfig)(configRequest, configPath);
const config = configAndEffectiveFile == null ? {} : configAndEffectiveFile.result;
if (configFromOptions != null) {
mergePublish(config, configFromOptions);
}
if (configAndEffectiveFile != null) {
builder_util_1.log.info({ file: configAndEffectiveFile.configFile == null ? 'package.json ("build" field)' : configAndEffectiveFile.configFile }, "loaded configuration");
}
if (config.extends == null && config.extends !== null) {
const metadata = (await packageMetadata.value) || {};
const devDependencies = metadata.devDependencies;
const dependencies = metadata.dependencies;
if ((dependencies != null && "react-scripts" in dependencies) || (devDependencies != null && "react-scripts" in devDependencies)) {
config.extends = "react-cra";
}
else if (devDependencies != null && "electron-webpack" in devDependencies) {
let file = "electron-webpack/out/electron-builder.js";
try {
file = require.resolve(file);
}
catch (_ignore) {
file = require.resolve("electron-webpack/electron-builder.yml");
}
config.extends = `file:${file}`;
}
}
const parentConfigs = await loadParentConfigsRecursively(config.extends, async (configExtend) => {
if (configExtend === "react-cra") {
const result = await (0, rectCra_1.reactCra)(projectDir);
builder_util_1.log.info({ preset: configExtend }, "loaded parent configuration");
return result;
}
else {
const { configFile, result } = await (0, load_1.loadParentConfig)(configRequest, configExtend);
builder_util_1.log.info({ file: configFile }, "loaded parent configuration");
return result;
}
});
return doMergeConfigs([...parentConfigs, config]);
}
function asArray(value) {
return Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
}
async function loadParentConfigsRecursively(configExtends, loader) {
const configs = [];
for (const configExtend of asArray(configExtends)) {
const result = await loader(configExtend);
const parentConfigs = await loadParentConfigsRecursively(result.extends, loader);
configs.push(...parentConfigs, result);
}
return configs;
}
// normalize for easy merge
function normalizeFiles(configuration, name) {
let value = configuration[name];
if (value == null) {
return;
}
if (!Array.isArray(value)) {
value = [value];
}
itemLoop: for (let i = 0; i < value.length; i++) {
let item = value[i];
if (typeof item === "string") {
// merge with previous if possible
if (i !== 0) {
let prevItemIndex = i - 1;
let prevItem;
do {
prevItem = value[prevItemIndex--];
} while (prevItem == null);
if (prevItem.from == null && prevItem.to == null) {
if (prevItem.filter == null) {
prevItem.filter = [item];
}
else {
;
prevItem.filter.push(item);
}
value[i] = null;
continue itemLoop;
}
}
item = {
filter: [item],
};
value[i] = item;
}
else if (Array.isArray(item)) {
throw new Error(`${name} configuration is invalid, nested array not expected for index ${i}: ${item}`);
}
// make sure that merge logic is not complex - unify different presentations
if (item.from === ".") {
item.from = undefined;
}
if (item.to === ".") {
item.to = undefined;
}
if (item.filter != null && typeof item.filter === "string") {
item.filter = [item.filter];
}
}
configuration[name] = value.filter(it => it != null);
}
function isSimilarFileSet(value, other) {
return value.from === other.from && value.to === other.to;
}
function mergeFilters(value, other) {
return asArray(value).concat(asArray(other));
}
function mergeFileSets(lists) {
const result = [];
for (const list of lists) {
for (const item of list) {
const existingItem = result.find(i => isSimilarFileSet(i, item));
if (existingItem) {
existingItem.filter = mergeFilters(item.filter, existingItem.filter);
}
else {
result.push(item);
}
}
}
return result;
}
/**
* `doMergeConfigs` takes configs in the order you would pass them to
* Object.assign as sources.
*/
function doMergeConfigs(configs) {
for (const config of configs) {
normalizeFiles(config, "files");
normalizeFiles(config, "extraFiles");
normalizeFiles(config, "extraResources");
}
const result = (0, builder_util_1.deepAssign)(getDefaultConfig(), ...configs);
// `deepAssign` prioritises latter configs, while `mergeFilesSets` prioritises
// former configs, so we have to reverse the order, because latter configs
// must have higher priority.
configs = configs.slice().reverse();
result.files = mergeFileSets(configs.map(config => { var _a; return ((_a = config.files) !== null && _a !== void 0 ? _a : []); }));
return result;
}
function getDefaultConfig() {
return {
directories: {
output: "dist",
buildResources: "build",
},
};
}
const schemeDataPromise = new lazy_val_1.Lazy(() => (0, fs_extra_1.readJson)(path.join(__dirname, "..", "..", "..", "scheme.json")));
async function validateConfiguration(config, debugLogger) {
const extraMetadata = config.extraMetadata;
if (extraMetadata != null) {
if (extraMetadata.build != null) {
throw new builder_util_1.InvalidConfigurationError(`--em.build is deprecated, please specify as -c"`);
}
if (extraMetadata.directories != null) {
throw new builder_util_1.InvalidConfigurationError(`--em.directories is deprecated, please specify as -c.directories"`);
}
}
const oldConfig = config;
if (oldConfig.npmSkipBuildFromSource === false) {
throw new builder_util_1.InvalidConfigurationError(`npmSkipBuildFromSource is deprecated, please use buildDependenciesFromSource"`);
}
if (oldConfig.appImage != null && oldConfig.appImage.systemIntegration != null) {
throw new builder_util_1.InvalidConfigurationError(`appImage.systemIntegration is deprecated, https://github.com/TheAssassin/AppImageLauncher is used for desktop integration"`);
}
// noinspection JSUnusedGlobalSymbols
validateSchema(await schemeDataPromise.value, config, {
name: `electron-builder ${version_1.PACKAGE_VERSION}`,
postFormatter: (formattedError, error) => {
if (debugLogger.isEnabled) {
debugLogger.add("invalidConfig", (0, builder_util_1.safeStringifyJson)(error));
}
const site = "https://www.electron.build";
let url = `${site}/configuration`;
const targets = new Set(["mac", "dmg", "pkg", "mas", "win", "nsis", "appx", "linux", "appimage", "snap"]);
const dataPath = error.dataPath == null ? null : error.dataPath;
const targetPath = dataPath.startsWith(".") ? dataPath.substr(1).toLowerCase() : null;
if (targetPath != null && targets.has(targetPath)) {
url = `${site}/${targetPath}`;
}
return `${formattedError}\n How to fix:
1. Open ${url}
2. Search the option name on the page (or type in into Search to find across the docs).
* Not found? The option was deprecated or not exists (check spelling).
* Found? Check that the option in the appropriate place. e.g. "title" only in the "dmg", not in the root.
`;
},
});
}
const DEFAULT_APP_DIR_NAMES = ["app", "www"];
async function computeDefaultAppDirectory(projectDir, userAppDir) {
if (userAppDir != null) {
const absolutePath = path.resolve(projectDir, userAppDir);
const stat = await (0, builder_util_1.statOrNull)(absolutePath);
if (stat == null) {
throw new builder_util_1.InvalidConfigurationError(`Application directory ${userAppDir} doesn't exist`);
}
else if (!stat.isDirectory()) {
throw new builder_util_1.InvalidConfigurationError(`Application directory ${userAppDir} is not a directory`);
}
else if (projectDir === absolutePath) {
builder_util_1.log.warn({ appDirectory: userAppDir }, `Specified application directory equals to project dir — superfluous or wrong configuration`);
}
return absolutePath;
}
for (const dir of DEFAULT_APP_DIR_NAMES) {
const absolutePath = path.join(projectDir, dir);
const packageJson = path.join(absolutePath, "package.json");
const stat = await (0, builder_util_1.statOrNull)(packageJson);
if (stat != null && stat.isFile()) {
return absolutePath;
}
}
return projectDir;
}
//# sourceMappingURL=config.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
import { Lazy } from "lazy-val";
import { DotenvParseInput } from "dotenv-expand";
export interface ReadConfigResult<T> {
readonly result: T;
readonly configFile: string | null;
}
export declare function findAndReadConfig<T>(request: ReadConfigRequest): Promise<ReadConfigResult<T> | null>;
export declare function orNullIfFileNotExist<T>(promise: Promise<T>): Promise<T | null>;
export declare function orIfFileNotExist<T>(promise: Promise<T>, fallbackValue: T): Promise<T>;
export interface ReadConfigRequest {
packageKey: string;
configFilename: string;
projectDir: string;
packageMetadata: Lazy<{
[key: string]: any;
} | null> | null;
}
export declare function loadConfig<T>(request: ReadConfigRequest): Promise<ReadConfigResult<T> | null>;
export declare function getConfig<T>(request: ReadConfigRequest, configPath?: string | null): Promise<ReadConfigResult<T> | null>;
export declare function loadParentConfig<T>(request: ReadConfigRequest, spec: string): Promise<ReadConfigResult<T>>;
export declare function loadEnv(envFile: string): Promise<DotenvParseInput | null>;

View File

@@ -0,0 +1,128 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.findAndReadConfig = findAndReadConfig;
exports.orNullIfFileNotExist = orNullIfFileNotExist;
exports.orIfFileNotExist = orIfFileNotExist;
exports.loadConfig = loadConfig;
exports.getConfig = getConfig;
exports.loadParentConfig = loadParentConfig;
exports.loadEnv = loadEnv;
const fs_1 = require("fs");
const js_yaml_1 = require("js-yaml");
const path = require("path");
const dotenv_1 = require("dotenv");
const config_file_ts_1 = require("config-file-ts");
const dotenv_expand_1 = require("dotenv-expand");
const resolve_1 = require("../resolve");
const builder_util_1 = require("builder-util");
async function readConfig(configFile, request) {
const data = await fs_1.promises.readFile(configFile, "utf8");
let result;
if (configFile.endsWith(".json5") || configFile.endsWith(".json")) {
result = require("json5").parse(data);
}
else if (configFile.endsWith(".js") || configFile.endsWith(".cjs") || configFile.endsWith(".mjs")) {
const json = await orNullIfFileNotExist(fs_1.promises.readFile(path.join(process.cwd(), "package.json"), "utf8"));
const moduleType = json === null ? null : JSON.parse(json).type;
result = await (0, resolve_1.resolveModule)(moduleType, configFile);
if (result.default != null) {
result = result.default;
}
if (typeof result === "function") {
result = result(request);
}
result = await Promise.resolve(result);
}
else if (configFile.endsWith(".ts")) {
result = (0, config_file_ts_1.loadTsConfig)(configFile);
if (typeof result === "function") {
result = result(request);
}
result = await Promise.resolve(result);
}
else if (configFile.endsWith(".toml")) {
result = require("toml").parse(data);
}
else {
result = (0, js_yaml_1.load)(data);
}
return { result, configFile };
}
async function findAndReadConfig(request) {
const prefix = request.configFilename;
for (const configFile of [`${prefix}.yml`, `${prefix}.yaml`, `${prefix}.json`, `${prefix}.json5`, `${prefix}.toml`, `${prefix}.js`, `${prefix}.cjs`, `${prefix}.ts`]) {
const data = await orNullIfFileNotExist(readConfig(path.join(request.projectDir, configFile), request));
if (data != null) {
return data;
}
}
return null;
}
function orNullIfFileNotExist(promise) {
return orIfFileNotExist(promise, null);
}
function orIfFileNotExist(promise, fallbackValue) {
return promise.catch(e => {
if (e.code === "ENOENT" || e.code === "ENOTDIR") {
return fallbackValue;
}
throw e;
});
}
async function loadConfig(request) {
let packageMetadata = request.packageMetadata == null ? null : await request.packageMetadata.value;
if (packageMetadata == null) {
const json = await orNullIfFileNotExist(fs_1.promises.readFile(path.join(request.projectDir, "package.json"), "utf8"));
packageMetadata = json == null ? null : JSON.parse(json);
}
const data = packageMetadata == null ? null : packageMetadata[request.packageKey];
return data == null ? findAndReadConfig(request) : { result: data, configFile: null };
}
function getConfig(request, configPath) {
if (configPath == null) {
return loadConfig(request);
}
else {
return readConfig(path.resolve(request.projectDir, configPath), request);
}
}
async function loadParentConfig(request, spec) {
let isFileSpec;
if (spec.startsWith("file:")) {
spec = spec.substring("file:".length);
isFileSpec = true;
}
let parentConfig = await orNullIfFileNotExist(readConfig(path.resolve(request.projectDir, spec), request));
if (parentConfig == null && isFileSpec !== true) {
let resolved = null;
try {
resolved = require.resolve(spec);
}
catch (_e) {
// ignore
}
if (resolved != null) {
parentConfig = await readConfig(resolved, request);
}
}
if (parentConfig == null) {
throw new Error(`Cannot find parent config file: ${spec}`);
}
return parentConfig;
}
async function loadEnv(envFile) {
const data = await orNullIfFileNotExist(fs_1.promises.readFile(envFile, "utf8"));
if (data == null) {
return null;
}
const parsed = (0, dotenv_1.parse)(data);
builder_util_1.log.info({ envFile }, "injecting environment");
Object.entries(parsed).forEach(([key, value]) => {
if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
process.env[key] = value;
}
});
(0, dotenv_expand_1.expand)({ parsed });
return parsed;
}
//# sourceMappingURL=load.js.map

File diff suppressed because one or more lines are too long